diff options
| author | Gerd Moellmann | 2000-12-14 16:18:54 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2000-12-14 16:18:54 +0000 |
| commit | a432bfe5e7c4650bda0d1400918dbf8f6082b29e (patch) | |
| tree | 36e201cde56008391a0409f7d0f3e33749ddfdfe /src | |
| parent | 0b750d70055fc8a04dd08de64a7c88ae72352ba6 (diff) | |
| download | emacs-a432bfe5e7c4650bda0d1400918dbf8f6082b29e.tar.gz emacs-a432bfe5e7c4650bda0d1400918dbf8f6082b29e.zip | |
(Fformat): Prevent a buffer overrun when the format
specifies a precision.
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/src/editfns.c b/src/editfns.c index e83e92f1396..1c8bc4c007d 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -3118,17 +3118,45 @@ Use %% to put a single % into the output.") | |||
| 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 | int field_width, precision; | ||
| 3123 | 3124 | ||
| 3124 | /* Process a numeric arg and skip it. */ | 3125 | /* General format specifications look like |
| 3125 | minlen = atoi (format); | ||
| 3126 | if (minlen < 0) | ||
| 3127 | minlen = - minlen; | ||
| 3128 | 3126 | ||
| 3129 | while ((*format >= '0' && *format <= '9') | 3127 | '%' [flags] [field-width] [precision] format |
| 3130 | || *format == '-' || *format == ' ' || *format == '.') | 3128 | |
| 3131 | format++; | 3129 | where |
| 3130 | |||
| 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; |
| @@ -3204,7 +3232,11 @@ Use %% to put a single % into the output.") | |||
| 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 | { |
| @@ -3220,9 +3252,7 @@ Use %% to put a single % into the output.") | |||
| 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 | ||
| @@ -3374,6 +3404,9 @@ Use %% to put a single % into the output.") | |||
| 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); |