comparison src/editfns.c @ 34566:0370af7597d2

(Fformat): Prevent a buffer overrun when the format specifies a precision.
author Gerd Moellmann <gerd@gnu.org>
date Thu, 14 Dec 2000 16:18:54 +0000
parents 3b3a64fbcb05
children 3f17dfb2dac4
comparison
equal deleted inserted replaced
34565:5c6c44b995ef 34566:0370af7597d2
3116 3116
3117 n = 0; 3117 n = 0;
3118 while (format != end) 3118 while (format != end)
3119 if (*format++ == '%') 3119 if (*format++ == '%')
3120 { 3120 {
3121 int minlen, thissize = 0; 3121 int thissize = 0;
3122 unsigned char *this_format_start = format - 1; 3122 unsigned char *this_format_start = format - 1;
3123 3123 int field_width, precision;
3124 /* Process a numeric arg and skip it. */ 3124
3125 minlen = atoi (format); 3125 /* General format specifications look like
3126 if (minlen < 0) 3126
3127 minlen = - minlen; 3127 '%' [flags] [field-width] [precision] format
3128 3128
3129 while ((*format >= '0' && *format <= '9') 3129 where
3130 || *format == '-' || *format == ' ' || *format == '.') 3130
3131 format++; 3131 flags ::= [#-* 0]+
3132 field-width ::= [0-9]+
3133 precision ::= '.' [0-9]*
3134
3135 If a field-width is specified, it specifies to which width
3136 the output should be padded with blanks, iff the output
3137 string is shorter than field-width.
3138
3139 if precision is specified, it specifies the number of
3140 digits to print after the '.' for floats, or the max.
3141 number of chars to print from a string. */
3142
3143 precision = field_width = 0;
3144
3145 while (index ("-*# 0", *format))
3146 ++format;
3147
3148 if (*format >= '0' && *format <= '9')
3149 {
3150 for (field_width = 0; *format >= '0' && *format <= '9'; ++format)
3151 field_width = 10 * field_width + *format - '0';
3152 }
3153
3154 if (*format == '.')
3155 {
3156 ++format;
3157 for (precision = 0; *format >= '0' && *format <= '9'; ++format)
3158 precision = 10 * precision + *format - '0';
3159 }
3132 3160
3133 if (format - this_format_start + 1 > longest_format) 3161 if (format - this_format_start + 1 > longest_format)
3134 longest_format = format - this_format_start + 1; 3162 longest_format = format - this_format_start + 1;
3135 3163
3136 if (format == end) 3164 if (format == end)
3202 } 3230 }
3203 else if (FLOATP (args[n]) && *format != 's') 3231 else if (FLOATP (args[n]) && *format != 's')
3204 { 3232 {
3205 if (! (*format == 'e' || *format == 'f' || *format == 'g')) 3233 if (! (*format == 'e' || *format == 'f' || *format == 'g'))
3206 args[n] = Ftruncate (args[n], Qnil); 3234 args[n] = Ftruncate (args[n], Qnil);
3207 thissize = 200; 3235
3236 /* Note that we're using sprintf to print floats,
3237 so we have to take into account what that function
3238 prints. */
3239 thissize = 200 + precision;
3208 } 3240 }
3209 else 3241 else
3210 { 3242 {
3211 /* Anything but a string, convert to a string using princ. */ 3243 /* Anything but a string, convert to a string using princ. */
3212 register Lisp_Object tem; 3244 register Lisp_Object tem;
3218 } 3250 }
3219 args[n] = tem; 3251 args[n] = tem;
3220 goto string; 3252 goto string;
3221 } 3253 }
3222 3254
3223 if (thissize < minlen) 3255 thissize = max (field_width, thissize);
3224 thissize = minlen;
3225
3226 total += thissize + 4; 3256 total += thissize + 4;
3227 } 3257 }
3228 3258
3229 /* Now we can no longer jump to retry. 3259 /* Now we can no longer jump to retry.
3230 TOTAL and LONGEST_FORMAT are known for certain. */ 3260 TOTAL and LONGEST_FORMAT are known for certain. */
3372 } 3402 }
3373 else 3403 else
3374 *p++ = *format++, nchars++; 3404 *p++ = *format++, nchars++;
3375 } 3405 }
3376 3406
3407 if (p > buf + total + 1)
3408 abort ();
3409
3377 if (maybe_combine_byte) 3410 if (maybe_combine_byte)
3378 nchars = multibyte_chars_in_text (buf, p - buf); 3411 nchars = multibyte_chars_in_text (buf, p - buf);
3379 val = make_specified_string (buf, nchars, p - buf, multibyte); 3412 val = make_specified_string (buf, nchars, p - buf, multibyte);
3380 3413
3381 /* If we allocated BUF with malloc, free it too. */ 3414 /* If we allocated BUF with malloc, free it too. */