# HG changeset patch # User Gerd Moellmann # Date 976810734 0 # Node ID 0370af7597d28eb4b30a672de0a6462072b83913 # Parent 5c6c44b995ef8c935cf0e6ecd7d80eac73a7eec1 (Fformat): Prevent a buffer overrun when the format specifies a precision. diff -r 5c6c44b995ef -r 0370af7597d2 src/editfns.c --- a/src/editfns.c Thu Dec 14 15:20:27 2000 +0000 +++ b/src/editfns.c Thu Dec 14 16:18:54 2000 +0000 @@ -3118,17 +3118,45 @@ while (format != end) if (*format++ == '%') { - int minlen, thissize = 0; + int thissize = 0; unsigned char *this_format_start = format - 1; - - /* Process a numeric arg and skip it. */ - minlen = atoi (format); - if (minlen < 0) - minlen = - minlen; - - while ((*format >= '0' && *format <= '9') - || *format == '-' || *format == ' ' || *format == '.') - format++; + int field_width, precision; + + /* General format specifications look like + + '%' [flags] [field-width] [precision] format + + where + + flags ::= [#-* 0]+ + field-width ::= [0-9]+ + precision ::= '.' [0-9]* + + If a field-width is specified, it specifies to which width + the output should be padded with blanks, iff the output + string is shorter than field-width. + + if precision is specified, it specifies the number of + digits to print after the '.' for floats, or the max. + number of chars to print from a string. */ + + precision = field_width = 0; + + while (index ("-*# 0", *format)) + ++format; + + if (*format >= '0' && *format <= '9') + { + for (field_width = 0; *format >= '0' && *format <= '9'; ++format) + field_width = 10 * field_width + *format - '0'; + } + + if (*format == '.') + { + ++format; + for (precision = 0; *format >= '0' && *format <= '9'; ++format) + precision = 10 * precision + *format - '0'; + } if (format - this_format_start + 1 > longest_format) longest_format = format - this_format_start + 1; @@ -3204,7 +3232,11 @@ { if (! (*format == 'e' || *format == 'f' || *format == 'g')) args[n] = Ftruncate (args[n], Qnil); - thissize = 200; + + /* Note that we're using sprintf to print floats, + so we have to take into account what that function + prints. */ + thissize = 200 + precision; } else { @@ -3220,9 +3252,7 @@ goto string; } - if (thissize < minlen) - thissize = minlen; - + thissize = max (field_width, thissize); total += thissize + 4; } @@ -3374,6 +3404,9 @@ *p++ = *format++, nchars++; } + if (p > buf + total + 1) + abort (); + if (maybe_combine_byte) nchars = multibyte_chars_in_text (buf, p - buf); val = make_specified_string (buf, nchars, p - buf, multibyte);