fakesnprintf.h
上传用户:lukesailor
上传日期:2007-01-04
资源大小:27k
文件大小:3k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /* $Id: fakesnprintf.h,v 1.1 1997/09/09 18:52:32 agulbra Exp $ */
  2. /*
  3.  *  Not sure why the vendors supposedly selling robust Unix versions
  4.  *  have yet to implement the size-restricted variants of the stdio
  5.  *  formatting routines.  Their lack is the single biggest cause of
  6.  *  buffer-overrun security problems.
  7.  *
  8.  *  This code implements a secure replacement if your O/S:
  9.  *
  10.  * a.  Doesn't have a real [v]snprintf()
  11.  * b.  Does have an mprotect(2) call that can be pointed
  12.  *     at arbitrary pages.
  13.  *
  14.  *  It doesn't implement full [v]snprintf() semantics, just
  15.  *  sufficient to keep troll-ftpd happy.  For example, if
  16.  *  an overrun occurs, the function will just return -1.
  17.  *
  18.  *  The code is known to work on:
  19.  *
  20.  * Solaris 2.4
  21.  * Irix 5.3
  22.  * Ultrix 4.4  (with -DHAVE_GETPAGESIZE)
  23.  *
  24.  *  The code is known NOT to work on:
  25.  *
  26.  * HP/UX 9.01
  27.  * AIX 3.2.5
  28.  */
  29. #ifndef FAKESNPRINTF_H
  30. #define FAKESNPRINTF_H
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <stdarg.h>
  34. #include <malloc.h>
  35. #include <string.h>
  36. #include <sys/types.h>
  37. #include <sys/mman.h>
  38. #include <unistd.h>
  39. #include <signal.h>
  40. #include <errno.h>
  41. /*
  42. **  Insist on at least this much space for the format area.
  43. */
  44. #define SPRINTF_MINAREA 1024
  45. static int sys_pagesize(void)
  46. {
  47. #if defined(_SC_PAGESIZE)
  48. return (int)sysconf(_SC_PAGESIZE);
  49. #else
  50. #if defined(_SC_PAGE_SIZE)
  51. return (int)sysconf(_SC_PAGE_SIZE);
  52. #else
  53. #if defined(HAVE_GETPAGESIZE)
  54. return getpagesize();
  55. #else
  56. #error Need to configure ftpd_getpagesize() in fake-snprintf.c
  57. #endif
  58. #endif
  59. #endif
  60. }
  61. static char *snprintf_area = 0;
  62. static int snprintf_areasize = 0;
  63. static void snprintf_init(void)
  64. {
  65. int pagesize, allocsize;
  66. char *area;
  67. unsigned long addr;
  68. snprintf_areasize = pagesize = sys_pagesize();
  69. if(snprintf_areasize < SPRINTF_MINAREA)
  70. {
  71. if(SPRINTF_MINAREA % pagesize)
  72. snprintf_areasize = pagesize *
  73. (SPRINTF_MINAREA/pagesize + 1);
  74. else
  75. snprintf_areasize = SPRINTF_MINAREA;
  76. }
  77. allocsize = snprintf_areasize + pagesize*2;
  78. area = malloc(allocsize);
  79. if(!area)
  80. {
  81. printf("421 Out of memory in vsnprintfrn");
  82. fflush(stdout);
  83. exit(6);
  84. }
  85. addr = (unsigned long)area;
  86. if(addr % pagesize)
  87. {
  88. int offset = pagesize - (addr % pagesize);
  89. addr += offset;
  90. area = (char *)addr;
  91. }
  92. if(mprotect((caddr_t)area + snprintf_areasize, pagesize, PROT_READ) < 0)
  93. {
  94. printf("421 Mprotect() failed -- %srn", strerror(errno));
  95. exit(6);
  96. }
  97. snprintf_area = area;
  98. }
  99. static void snprintf_catch(int sig)
  100. {
  101. printf("421 Buffer overrun detectedrn");
  102. exit(sig);
  103. }
  104. int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
  105. {
  106. int len, lim;
  107. void (*disp)(int);
  108. if(size <= 0)
  109. return -1;
  110. buf[0] = 0;
  111. /*
  112. **  Minor optimization saves setting up signal handling
  113. */
  114. if(!strchr(fmt, '%') && (len = strlen(fmt)) < (int)size-1)
  115. {
  116. strcpy(buf, fmt);
  117. return len;
  118. }
  119. if(!snprintf_area)
  120. snprintf_init();
  121. disp = signal(SIGSEGV, snprintf_catch);
  122. len = vsprintf(snprintf_area, fmt, ap);
  123. signal(SIGSEGV, disp);
  124. if(len < 0)
  125. return len;
  126. lim = len;
  127. if(lim > (int)size - 1)
  128. lim = size - 1;
  129. snprintf_area[lim] = 0;
  130. strcpy(buf, snprintf_area);
  131. return len;
  132. }
  133. int snprintf(char *buf, size_t size, const char *fmt, ...)
  134. {
  135. int len;
  136. va_list ap;
  137. va_start(ap, fmt);
  138. len = vsnprintf(buf, size, fmt, ap);
  139. va_end(ap);
  140. return len;
  141. }
  142. #endif /* FAKESNPRINTF_H */