FreeBSD就是一种运行在Intel平台上、可以自由使用的开放源码Unix类系统。 FreeBSD的strfmon()函数使用了GET_NUMBER()宏,该宏没有检查整数溢出便将其值作为参数传送给了memmove()和memset()函数。 在strfmon()函数的源码中: - ---strfmon()-start--- ssize_t strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, ...) { va_list ap; char *dst; /* output destination pointer */ const char *fmt; /* current format poistion pointer */ struct lconv *lc; /* pointer to lconv structure */ char *asciivalue; /* formatted double pointer */ int flags; /* formatting options */ int pad_char; /* padding character */ int pad_size; /* pad size */ int width; /* field width */ int left_prec; /* left precision */ int right_prec; /* right precision */ double value; /* just value */ char space_char = \'\' \'\'; /* space after currency */ char cs_precedes, /* values gathered from struct lconv */ sep_by_space, sign_posn, *signstr, *currency_symbol; char *tmpptr; /* temporary vars */ int sverrno; va_start(ap, format); lc = localeconv(); dst = s; fmt = format; asciivalue =...
FreeBSD就是一种运行在Intel平台上、可以自由使用的开放源码Unix类系统。 FreeBSD的strfmon()函数使用了GET_NUMBER()宏,该宏没有检查整数溢出便将其值作为参数传送给了memmove()和memset()函数。 在strfmon()函数的源码中: - ---strfmon()-start--- ssize_t strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, ...) { va_list ap; char *dst; /* output destination pointer */ const char *fmt; /* current format poistion pointer */ struct lconv *lc; /* pointer to lconv structure */ char *asciivalue; /* formatted double pointer */ int flags; /* formatting options */ int pad_char; /* padding character */ int pad_size; /* pad size */ int width; /* field width */ int left_prec; /* left precision */ int right_prec; /* right precision */ double value; /* just value */ char space_char = \'\' \'\'; /* space after currency */ char cs_precedes, /* values gathered from struct lconv */ sep_by_space, sign_posn, *signstr, *currency_symbol; char *tmpptr; /* temporary vars */ int sverrno; va_start(ap, format); lc = localeconv(); dst = s; fmt = format; asciivalue = NULL; currency_symbol = NULL; pad_size = 0; while (*fmt) { /* pass nonformating characters AS IS */ if (*fmt != \'\'\\%\'\') goto literal; /* \'\'\\%\'\' found ! */ /* \"\\%\\%\" mean just \'\'\\%\'\' */ if (*(fmt+1) == \'\'\\%\'\') { fmt++; literal: PRINT(*fmt++); continue; } /* set up initial values */ flags = (NEED_GROUPING|LOCALE_POSN); pad_char = \'\' \'\'; /* padding character is \"space\" */ left_prec = -1; /* no left precision specified */ right_prec = -1; /* no right precision specified */ width = -1; /* no width specified */ value = 0; /* we have no value to print now */ /* Flags */ while (1) { switch (*++fmt) { case \'\'=\'\': /* fill character */ pad_char = *++fmt; if (pad_char == \'\'\0\'\') goto format_error; continue; case \'\'^\'\': /* not group currency */ flags &= ~(NEED_GROUPING); continue; case \'\'+\'\': /* use locale defined signs */ if (flags & SIGN_POSN_USED) goto format_error; flags |= (SIGN_POSN_USED|LOCALE_POSN); continue; case \'\'(\'\': /* enclose negatives with () */ if (flags & SIGN_POSN_USED) goto format_error; flags |= (SIGN_POSN_USED|PARENTH_POSN); continue; case \'\'!\'\': /* suppress currency symbol */ flags |= SUPRESS_CURR_SYMBOL; continue; case \'\'-\'\': /* alignment (left) */ flags |= LEFT_JUSTIFY; continue; default: break; } break; } /* field Width */ if (isdigit((unsigned char)*fmt)) { GET_NUMBER(width); /* Do we have enough space to put number with * required width ? */ if (dst + width >= s + maxsize) goto e2big_error; } /* Left precision */ if (*fmt == \'\'#\'\') { if (!isdigit((unsigned char)*++fmt)) goto format_error; GET_NUMBER(left_prec); } /* Right precision */ if (*fmt == \'\'.\'\') { if (!isdigit((unsigned char)*++fmt)) goto format_error; GET_NUMBER(right_prec); } /* Conversion Charact