Mercurial > emacs
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. */ |