home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / patches / vsprintf.c < prev   
Encoding:
C/C++ Source or Header  |  2001-03-14  |  9.7 KB  |  491 lines

  1. /* 
  2.  * I added vsnprintf().
  3.  * Replace /usr/src/linux/lib/vsprintf.c.
  4.  * You can now use vsnprintf() in the kernel.
  5.  * Replace all vsprintf()'s that print into a buffer 
  6.  * 
  7.  * Be sure to NULL terminate the buffer everywhere you replace vsprintf()
  8.  * with vsnprintf(). By doing something like: buf[len-1] = '\0'; if you
  9.  * passed len to vsnprintf()
  10.  *
  11.  * [Update: It seems someone must have noticed a few of the overflows]
  12.  * [        a few weeks after I put this up.. the printk() overflow  ]
  13.  * [        has been fixed in the lastest kernel.. but there are     ]
  14.  * [        still way too many calls to *sprintf() functions...      ]
  15.  *
  16.  * Shok (Matt Conover), shok@dataforce.net
  17.  */
  18.  
  19. /*
  20.  *  linux/lib/vsprintf.c
  21.  *
  22.  *  Copyright (C) 1991, 1992  Linus Torvalds
  23.  */
  24.  
  25. /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  26. /*
  27.  * Wirzenius wrote this portably, Torvalds fucked it up :-)
  28.  */
  29.  
  30. #include <stdarg.h>
  31. #include <linux/types.h>
  32. #include <linux/string.h>
  33. #include <linux/ctype.h>
  34.  
  35. unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
  36. {
  37.     unsigned long result = 0,value;
  38.  
  39.     if (!base) {
  40.         base = 10;
  41.         if (*cp == '0') {
  42.             base = 8;
  43.             cp++;
  44.             if ((*cp == 'x') && isxdigit(cp[1])) {
  45.                 cp++;
  46.                 base = 16;
  47.             }
  48.         }
  49.     }
  50.     while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
  51.         ? toupper(*cp) : *cp)-'A'+10) < base) {
  52.         result = result*base + value;
  53.         cp++;
  54.     }
  55.     if (endp)
  56.         *endp = (char *)cp;
  57.     return result;
  58. }
  59.  
  60. /* we use this so that we can do without the ctype library */
  61. #define is_digit(c)    ((c) >= '0' && (c) <= '9')
  62.  
  63. static int skip_atoi(const char **s)
  64. {
  65.     int i=0;
  66.  
  67.     while (is_digit(**s))
  68.         i = i*10 + *((*s)++) - '0';
  69.     return i;
  70. }
  71.  
  72. #define ZEROPAD    1        /* pad with zero */
  73. #define SIGN    2        /* unsigned/signed long */
  74. #define PLUS    4        /* show plus */
  75. #define SPACE    8        /* space if plus */
  76. #define LEFT    16        /* left justified */
  77. #define SPECIAL    32        /* 0x */
  78. #define LARGE    64        /* use 'ABCDEF' instead of 'abcdef' */
  79.  
  80. #define do_div(n,base) ({ \
  81. int __res; \
  82. __res = ((unsigned long) n) % (unsigned) base; \
  83. n = ((unsigned long) n) / (unsigned) base; \
  84. __res; })
  85.  
  86. static char * number(char * str, long num, int base, int size, int precision
  87.     ,int type)
  88. {
  89.     char c,sign,tmp[66];
  90.     const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
  91.     int i;
  92.  
  93.     if (type & LARGE)
  94.         digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  95.     if (type & LEFT)
  96.         type &= ~ZEROPAD;
  97.     if (base < 2 || base > 36)
  98.         return 0;
  99.     c = (type & ZEROPAD) ? '0' : ' ';
  100.     sign = 0;
  101.     if (type & SIGN) {
  102.         if (num < 0) {
  103.             sign = '-';
  104.             num = -num;
  105.             size--;
  106.         } else if (type & PLUS) {
  107.             sign = '+';
  108.             size--;
  109.         } else if (type & SPACE) {
  110.             sign = ' ';
  111.             size--;
  112.         }
  113.     }
  114.     if (type & SPECIAL) {
  115.         if (base == 16)
  116.             size -= 2;
  117.         else if (base == 8)
  118.             size--;
  119.     }
  120.     i = 0;
  121.     if (num == 0)
  122.         tmp[i++]='0';
  123.     else while (num != 0)
  124.         tmp[i++] = digits[do_div(num,base)];
  125.     if (i > precision)
  126.         precision = i;
  127.     size -= precision;
  128.     if (!(type&(ZEROPAD+LEFT)))
  129.         while(size-->0)
  130.             *str++ = ' ';
  131.     if (sign)
  132.         *str++ = sign;
  133.     if (type & SPECIAL)
  134.         if (base==8)
  135.             *str++ = '0';
  136.         else if (base==16) {
  137.             *str++ = '0';
  138.             *str++ = digits[33];
  139.         }
  140.     if (!(type & LEFT))
  141.         while (size-- > 0)
  142.             *str++ = c;
  143.     while (i < precision--)
  144.         *str++ = '0';
  145.     while (i-- > 0)
  146.         *str++ = tmp[i];
  147.     while (size-- > 0)
  148.         *str++ = ' ';
  149.     return str;
  150. }
  151.  
  152. int vsprintf(char *buf, const char *fmt, va_list args)
  153. {
  154.     int len;
  155.     unsigned long num;
  156.     int i, base;
  157.     char * str;
  158.     const char *s;
  159.  
  160.     int flags;        /* flags to number() */
  161.  
  162.     int field_width;    /* width of output field */
  163.     int precision;        /* min. # of digits for integers; max
  164.                    number of chars for from string */
  165.     int qualifier;        /* 'h', 'l', or 'L' for integer fields */
  166.  
  167.     for (str=buf ; *fmt ; ++fmt) {
  168.         if (*fmt != '%') {
  169.             *str++ = *fmt;
  170.             continue;
  171.         }
  172.             
  173.         /* process flags */
  174.         flags = 0;
  175.         repeat:
  176.             ++fmt;        /* this also skips first '%' */
  177.             switch (*fmt) {
  178.                 case '-': flags |= LEFT; goto repeat;
  179.                 case '+': flags |= PLUS; goto repeat;
  180.                 case ' ': flags |= SPACE; goto repeat;
  181.                 case '#': flags |= SPECIAL; goto repeat;
  182.                 case '0': flags |= ZEROPAD; goto repeat;
  183.                 }
  184.         
  185.         /* get field width */
  186.         field_width = -1;
  187.         if (is_digit(*fmt))
  188.             field_width = skip_atoi(&fmt);
  189.         else if (*fmt == '*') {
  190.             ++fmt;
  191.             /* it's the next argument */
  192.             field_width = va_arg(args, int);
  193.             if (field_width < 0) {
  194.                 field_width = -field_width;
  195.                 flags |= LEFT;
  196.             }
  197.         }
  198.  
  199.         /* get the precision */
  200.         precision = -1;
  201.         if (*fmt == '.') {
  202.             ++fmt;    
  203.             if (is_digit(*fmt))
  204.                 precision = skip_atoi(&fmt);
  205.             else if (*fmt == '*') {
  206.                 ++fmt;
  207.                 /* it's the next argument */
  208.                 precision = va_arg(args, int);
  209.             }
  210.             if (precision < 0)
  211.                 precision = 0;
  212.         }
  213.  
  214.         /* get the conversion qualifier */
  215.         qualifier = -1;
  216.         if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  217.             qualifier = *fmt;
  218.             ++fmt;
  219.         }
  220.  
  221.         /* default base */
  222.         base = 10;
  223.  
  224.         switch (*fmt) {
  225.         case 'c':
  226.             if (!(flags & LEFT))
  227.                 while (--field_width > 0)
  228.                     *str++ = ' ';
  229.             *str++ = (unsigned char) va_arg(args, int);
  230.             while (--field_width > 0)
  231.                 *str++ = ' ';
  232.             continue;
  233.  
  234.         case 's':
  235.             s = va_arg(args, char *);
  236.             if (!s)
  237.                 s = "<NULL>";
  238.  
  239.             len = strnlen(s, precision);
  240.  
  241.             if (!(flags & LEFT))
  242.                 while (len < field_width--)
  243.                     *str++ = ' ';
  244.             for (i = 0; i < len; ++i)
  245.                 *str++ = *s++;
  246.             while (len < field_width--)
  247.                 *str++ = ' ';
  248.             continue;
  249.  
  250.         case 'p':
  251.             if (field_width == -1) {
  252.                 field_width = 2*sizeof(void *);
  253.                 flags |= ZEROPAD;
  254.             }
  255.             str = number(str,
  256.                 (unsigned long) va_arg(args, void *), 16,
  257.                 field_width, precision, flags);
  258.             continue;
  259.  
  260.  
  261.         case 'n':
  262.             if (qualifier == 'l') {
  263.                 long * ip = va_arg(args, long *);
  264.                 *ip = (str - buf);
  265.             } else {
  266.                 int * ip = va_arg(args, int *);
  267.                 *ip = (str - buf);
  268.             }
  269.             continue;
  270.  
  271.         /* integer number formats - set up the flags and "break" */
  272.         case 'o':
  273.             base = 8;
  274.             break;
  275.  
  276.         case 'X':
  277.             flags |= LARGE;
  278.         case 'x':
  279.             base = 16;
  280.             break;
  281.  
  282.         case 'd':
  283.         case 'i':
  284.             flags |= SIGN;
  285.         case 'u':
  286.             break;
  287.  
  288.         default:
  289.             if (*fmt != '%')
  290.                 *str++ = '%';
  291.             if (*fmt)
  292.                 *str++ = *fmt;
  293.             else
  294.                 --fmt;
  295.             continue;
  296.         }
  297.         if (qualifier == 'l')
  298.             num = va_arg(args, unsigned long);
  299.         else if (qualifier == 'h')
  300.             if (flags & SIGN)
  301.                 num = va_arg(args, short);
  302.             else
  303.                 num = va_arg(args, unsigned short);
  304.         else if (flags & SIGN)
  305.             num = va_arg(args, int);
  306.         else
  307.             num = va_arg(args, unsigned int);
  308.         str = number(str, num, base, field_width, precision, flags);
  309.     }
  310.     *str = '\0';
  311.     return str-buf;
  312. }
  313.  
  314.  
  315. int vsnprintf(char *buf, int size, const char *fmt, va_list args)
  316. {
  317.     int len;
  318.     unsigned long num;
  319.     int i, base;
  320.     char * str;
  321.     const char *s;
  322.  
  323.     int flags;        /* flags to number() */
  324.  
  325.     int field_width;    /* width of output field */
  326.     int precision;        /* min. # of digits for integers; max
  327.                    number of chars for from string */
  328.     int qualifier;        /* 'h', 'l', or 'L' for integer fields */
  329.  
  330.         register int cursize;
  331.  
  332.     for (str=buf, cursize = 1; *fmt, cursize < size ; ++fmt, cursize++) {
  333.         if (*fmt != '%') {
  334.             *str++ = *fmt;
  335.             continue;
  336.         }
  337.             
  338.         /* process flags */
  339.         flags = 0;
  340.         repeat:
  341.             ++fmt;        /* this also skips first '%' */
  342.             switch (*fmt) {
  343.                 case '-': flags |= LEFT; goto repeat;
  344.                 case '+': flags |= PLUS; goto repeat;
  345.                 case ' ': flags |= SPACE; goto repeat;
  346.                 case '#': flags |= SPECIAL; goto repeat;
  347.                 case '0': flags |= ZEROPAD; goto repeat;
  348.                 }
  349.         
  350.         /* get field width */
  351.         field_width = -1;
  352.         if (is_digit(*fmt))
  353.             field_width = skip_atoi(&fmt);
  354.         else if (*fmt == '*') {
  355.             ++fmt;
  356.             /* it's the next argument */
  357.             field_width = va_arg(args, int);
  358.             if (field_width < 0) {
  359.                 field_width = -field_width;
  360.                 flags |= LEFT;
  361.             }
  362.         }
  363.  
  364.         /* get the precision */
  365.         precision = -1;
  366.         if (*fmt == '.') {
  367.             ++fmt;    
  368.             if (is_digit(*fmt))
  369.                 precision = skip_atoi(&fmt);
  370.             else if (*fmt == '*') {
  371.                 ++fmt;
  372.                 /* it's the next argument */
  373.                 precision = va_arg(args, int);
  374.             }
  375.             if (precision < 0)
  376.                 precision = 0;
  377.         }
  378.  
  379.         /* get the conversion qualifier */
  380.         qualifier = -1;
  381.         if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  382.             qualifier = *fmt;
  383.             ++fmt;
  384.         }
  385.  
  386.         /* default base */
  387.         base = 10;
  388.  
  389.         switch (*fmt) {
  390.         case 'c':
  391.             if (!(flags & LEFT))
  392.                 while (--field_width > 0)
  393.                     *str++ = ' ';
  394.             *str++ = (unsigned char) va_arg(args, int);
  395.             while (--field_width > 0)
  396.                 *str++ = ' ';
  397.             continue;
  398.  
  399.         case 's':
  400.             s = va_arg(args, char *);
  401.             if (!s)
  402.                 s = "<NULL>";
  403.  
  404.             len = strnlen(s, precision);
  405.  
  406.             if (!(flags & LEFT))
  407.                 while (len < field_width--)
  408.                     *str++ = ' ';
  409.             for (i = 0; i < len; ++i)
  410.                 *str++ = *s++;
  411.             while (len < field_width--)
  412.                 *str++ = ' ';
  413.             continue;
  414.  
  415.         case 'p':
  416.             if (field_width == -1) {
  417.                 field_width = 2*sizeof(void *);
  418.                 flags |= ZEROPAD;
  419.             }
  420.             str = number(str,
  421.                 (unsigned long) va_arg(args, void *), 16,
  422.                 field_width, precision, flags);
  423.             continue;
  424.  
  425.  
  426.         case 'n':
  427.             if (qualifier == 'l') {
  428.                 long * ip = va_arg(args, long *);
  429.                 *ip = (str - buf);
  430.             } else {
  431.                 int * ip = va_arg(args, int *);
  432.                 *ip = (str - buf);
  433.             }
  434.             continue;
  435.  
  436.         /* integer number formats - set up the flags and "break" */
  437.         case 'o':
  438.             base = 8;
  439.             break;
  440.  
  441.         case 'X':
  442.             flags |= LARGE;
  443.         case 'x':
  444.             base = 16;
  445.             break;
  446.  
  447.         case 'd':
  448.         case 'i':
  449.             flags |= SIGN;
  450.         case 'u':
  451.             break;
  452.  
  453.         default:
  454.             if (*fmt != '%')
  455.                 *str++ = '%';
  456.             if (*fmt)
  457.                 *str++ = *fmt;
  458.             else
  459.                 --fmt;
  460.             continue;
  461.         }
  462.         if (qualifier == 'l')
  463.             num = va_arg(args, unsigned long);
  464.         else if (qualifier == 'h')
  465.             if (flags & SIGN)
  466.                 num = va_arg(args, short);
  467.             else
  468.                 num = va_arg(args, unsigned short);
  469.         else if (flags & SIGN)
  470.             num = va_arg(args, int);
  471.         else
  472.             num = va_arg(args, unsigned int);
  473.         str = number(str, num, base, field_width, precision, flags);
  474.     }
  475.     *str = '\0';
  476.     return str-buf;
  477. }
  478.  
  479.  
  480. int sprintf(char * buf, const char *fmt, ...)
  481. {
  482.     va_list args;
  483.     int i;
  484.  
  485.     va_start(args, fmt);
  486.     i=vsprintf(buf,fmt,args);
  487.     va_end(args);
  488.     return i;
  489. }
  490.  
  491.