X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fstring.c;h=f64641dd6c5fe57969df80180697e6cfb78d8cb7;hb=261cf46666b7d82f7301f86cfd0719bfe35ffa0b;hp=2f69cd494ff5c1bcf57a04a7350a37759f5c5371;hpb=c988f1f4faa9f679f79beddf3c14676c5dcb8e28;p=exim.git diff --git a/src/src/string.c b/src/src/string.c index 2f69cd494..f64641dd6 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/string.c,v 1.2 2005/01/04 10:00:42 ph10 Exp $ */ +/* $Cambridge: exim/src/src/string.c,v 1.7 2005/06/20 10:04:55 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -944,9 +944,9 @@ on whether the variable length list of data arguments are given explicitly or as a va_list item. The formats are the usual printf() ones, with some omissions (never used) and -two additions for strings: %S forces lower case, %#s or %#S prints nothing for -a NULL string. Without the # "NULL" is printed (useful in debugging). There is -also the addition of %D, which inserts the date in the form used for +two additions for strings: %S forces lower case, and %#s or %#S prints nothing +for a NULL string. Without the # "NULL" is printed (useful in debugging). There +is also the addition of %D, which inserts the date in the form used for datestamped log files. Arguments: @@ -973,6 +973,8 @@ return yield; BOOL string_vformat(uschar *buffer, int buflen, char *format, va_list ap) { +enum { L_NORMAL, L_SHORT, L_LONG, L_LONGLONG, L_LONGDOUBLE }; + BOOL yield = TRUE; int width, precision; char *fp = format; /* Deliberately not unsigned */ @@ -985,6 +987,7 @@ string_datestamp_offset = -1; /* Datestamp not inserted */ while (*fp != 0) { + int length = L_NORMAL; int *nptr; int slen; char *null = "NULL"; /* ) These variables */ @@ -1038,7 +1041,25 @@ while (*fp != 0) } } - if (strchr("hlL", *fp) != NULL) fp++; + /* Skip over 'h', 'L', 'l', and 'll', remembering the item length */ + + if (*fp == 'h') + { fp++; length = L_SHORT; } + else if (*fp == 'L') + { fp++; length = L_LONGDOUBLE; } + else if (*fp == 'l') + { + if (fp[1] == 'l') + { + fp += 2; + length = L_LONGLONG; + } + else + { + fp++; + length = L_LONG; + } + } /* Handle each specific format type. */ @@ -1054,10 +1075,21 @@ while (*fp != 0) case 'u': case 'x': case 'X': - if (p >= last - 12) { yield = FALSE; goto END_FORMAT; } + if (p >= last - ((length > L_LONG)? 24 : 12)) + { yield = FALSE; goto END_FORMAT; } strncpy(newformat, item_start, fp - item_start); newformat[fp - item_start] = 0; - sprintf(CS p, newformat, va_arg(ap, int)); + + /* Short int is promoted to int when passing through ..., so we must use + int for va_arg(). */ + + switch(length) + { + case L_SHORT: + case L_NORMAL: sprintf(CS p, newformat, va_arg(ap, int)); break; + case L_LONG: sprintf(CS p, newformat, va_arg(ap, long int)); break; + case L_LONGLONG: sprintf(CS p, newformat, va_arg(ap, LONGLONG_T)); break; + } while (*p) p++; break; @@ -1070,9 +1102,11 @@ while (*fp != 0) break; /* %f format is inherently insecure if the numbers that it may be - handed are unknown (e.g. 1e300). However, in Exim, the only use of %f - is for printing load averages, and these are actually stored as integers - (load average * 1000) so the size of the numbers is constrained. */ + handed are unknown (e.g. 1e300). However, in Exim, %f is used for + printing load averages, and these are actually stored as integers + (load average * 1000) so the size of the numbers is constrained. + It is also used for formatting sending rates, where the simplicity + of the format prevents overflow. */ case 'f': case 'e': @@ -1083,7 +1117,10 @@ while (*fp != 0) if (p >= last - precision - 8) { yield = FALSE; goto END_FORMAT; } strncpy(newformat, item_start, fp - item_start); newformat[fp-item_start] = 0; - sprintf(CS p, newformat, va_arg(ap, double)); + if (length == L_LONGDOUBLE) + sprintf(CS p, newformat, va_arg(ap, long double)); + else + sprintf(CS p, newformat, va_arg(ap, double)); while (*p) p++; break;