aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2011-05-12 23:12:24 -0700
committerPaul Eggert2011-05-12 23:12:24 -0700
commit2d165e9dc58924db64f73791a638c136bc6324d7 (patch)
treedc24f2019b1fb5e0d0f3cae4b760b257fbca69e8 /src
parentbcfc5c821c672e38e5d4fad78347ab3c3f4352f7 (diff)
downloademacs-2d165e9dc58924db64f73791a638c136bc6324d7.tar.gz
emacs-2d165e9dc58924db64f73791a638c136bc6324d7.zip
* editfns.c (Fformat): Fix several integer overflow problems.
For example, without this change, (format "%2147483648d" 1) dumps core on x86-64 GNU/Linux. Use EMACS_INT, not size_t, for sizes, since we prefer using signed values, and EMACS_INT will be big enough soon, even on 32-bit hosts. Also, prefer EMACS_INT to int for sizes. Don't assume that pI is either "l" or ""; it might be "ll" or "I64". Check for width and precision greater than INT_MAX, as this can make sprintf go kaflooey. (Bug#8668)
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog9
-rw-r--r--src/editfns.c64
2 files changed, 45 insertions, 28 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 378d8a22808..9bdbb9a7d18 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,14 @@
12011-05-13 Paul Eggert <eggert@cs.ucla.edu> 12011-05-13 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 * editfns.c (Fformat): Fix several integer overflow problems.
4 For example, without this change, (format "%2147483648d" 1) dumps
5 core on x86-64 GNU/Linux. Use EMACS_INT, not size_t, for sizes,
6 since we prefer using signed values, and EMACS_INT will be big
7 enough soon, even on 32-bit hosts. Also, prefer EMACS_INT to int
8 for sizes. Don't assume that pI is either "l" or ""; it might be
9 "ll" or "I64". Check for width and precision greater than
10 INT_MAX, as this can make sprintf go kaflooey. (Bug#8668)
11
3 * dispextern.h (struct image): Don't assume time_t <= unsigned long. 12 * dispextern.h (struct image): Don't assume time_t <= unsigned long.
4 * image.c (clear_image_cache): Likewise. 13 * image.c (clear_image_cache): Likewise.
5 14
diff --git a/src/editfns.c b/src/editfns.c
index 5e1dcce0275..b5ccb481c43 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3583,11 +3583,12 @@ specifier truncates the string to the given width.
3583usage: (format STRING &rest OBJECTS) */) 3583usage: (format STRING &rest OBJECTS) */)
3584 (size_t nargs, register Lisp_Object *args) 3584 (size_t nargs, register Lisp_Object *args)
3585{ 3585{
3586 register size_t n; /* The number of the next arg to substitute */ 3586 register EMACS_INT n; /* The number of the next arg to substitute */
3587 register size_t total; /* An estimate of the final length */ 3587 register EMACS_INT total; /* An estimate of the final length */
3588 int pIlen = sizeof pI - 1;
3588 char *buf, *p; 3589 char *buf, *p;
3589 register char *format, *end, *format_start; 3590 register char *format, *end, *format_start;
3590 int nchars; 3591 EMACS_INT nchars;
3591 /* Nonzero if the output should be a multibyte string, 3592 /* Nonzero if the output should be a multibyte string,
3592 which is true if any of the inputs is one. */ 3593 which is true if any of the inputs is one. */
3593 int multibyte = 0; 3594 int multibyte = 0;
@@ -3603,7 +3604,7 @@ usage: (format STRING &rest OBJECTS) */)
3603 no argument, *will* be assigned to in the case that a `%' and `.' 3604 no argument, *will* be assigned to in the case that a `%' and `.'
3604 occur after the final format specifier. */ 3605 occur after the final format specifier. */
3605 int *precision = (int *) (alloca ((nargs + 1) * sizeof (int))); 3606 int *precision = (int *) (alloca ((nargs + 1) * sizeof (int)));
3606 int longest_format; 3607 EMACS_INT longest_format;
3607 Lisp_Object val; 3608 Lisp_Object val;
3608 int arg_intervals = 0; 3609 int arg_intervals = 0;
3609 USE_SAFE_ALLOCA; 3610 USE_SAFE_ALLOCA;
@@ -3619,7 +3620,8 @@ usage: (format STRING &rest OBJECTS) */)
3619 info[0] is unused. Unused elements have -1 for start. */ 3620 info[0] is unused. Unused elements have -1 for start. */
3620 struct info 3621 struct info
3621 { 3622 {
3622 int start, end, intervals; 3623 EMACS_INT start, end;
3624 int intervals;
3623 } *info = 0; 3625 } *info = 0;
3624 3626
3625 /* It should not be necessary to GCPRO ARGS, because 3627 /* It should not be necessary to GCPRO ARGS, because
@@ -3660,8 +3662,8 @@ usage: (format STRING &rest OBJECTS) */)
3660 3662
3661 /* Allocate the info and discarded tables. */ 3663 /* Allocate the info and discarded tables. */
3662 { 3664 {
3663 size_t nbytes = (nargs+1) * sizeof *info; 3665 EMACS_INT nbytes = (nargs + 1) * sizeof *info;
3664 size_t i; 3666 EMACS_INT i;
3665 if (!info) 3667 if (!info)
3666 info = (struct info *) alloca (nbytes); 3668 info = (struct info *) alloca (nbytes);
3667 memset (info, 0, nbytes); 3669 memset (info, 0, nbytes);
@@ -3706,25 +3708,33 @@ usage: (format STRING &rest OBJECTS) */)
3706 || * format == ' ' || *format == '+')) 3708 || * format == ' ' || *format == '+'))
3707 ++format; 3709 ++format;
3708 3710
3711 /* Parse width and precision, limiting them to the range of 'int'
3712 because otherwise the underyling sprintf may go kaflooey. */
3713
3709 if (*format >= '0' && *format <= '9') 3714 if (*format >= '0' && *format <= '9')
3710 { 3715 {
3711 for (field_width = 0; *format >= '0' && *format <= '9'; ++format) 3716 char *width_end;
3712 field_width = 10 * field_width + *format - '0'; 3717 unsigned long width = strtoul (format, &width_end, 10);
3718 if (INT_MAX < width)
3719 error ("Format string field width too large");
3720 field_width = width;
3721 format = width_end;
3713 } 3722 }
3714 3723
3715 /* N is not incremented for another few lines below, so refer to 3724 /* N is not incremented for another few lines below, so refer to
3716 element N+1 (which might be precision[NARGS]). */ 3725 element N+1 (which might be precision[NARGS]). */
3717 if (*format == '.') 3726 if (*format == '.')
3718 { 3727 {
3719 ++format; 3728 char *prec_end;
3720 for (precision[n+1] = 0; *format >= '0' && *format <= '9'; ++format) 3729 unsigned long prec = strtoul (format + 1, &prec_end, 10);
3721 precision[n+1] = 10 * precision[n+1] + *format - '0'; 3730 if (INT_MAX < prec)
3731 error ("Format string precision too large");
3732 precision[n + 1] = prec;
3733 format = prec_end;
3722 } 3734 }
3723 3735
3724 /* Extra +1 for 'l' that we may need to insert into the 3736 if (longest_format < format - this_format_start + pIlen + 1)
3725 format. */ 3737 longest_format = format - this_format_start + pIlen + 1;
3726 if (format - this_format_start + 2 > longest_format)
3727 longest_format = format - this_format_start + 2;
3728 3738
3729 if (format == end) 3739 if (format == end)
3730 error ("Format string ends in middle of format specifier"); 3740 error ("Format string ends in middle of format specifier");
@@ -3975,24 +3985,22 @@ usage: (format STRING &rest OBJECTS) */)
3975 } 3985 }
3976 else if (INTEGERP (args[n]) || FLOATP (args[n])) 3986 else if (INTEGERP (args[n]) || FLOATP (args[n]))
3977 { 3987 {
3978 int this_nchars; 3988 EMACS_INT this_nchars;
3989 EMACS_INT this_format_len = format - this_format_start;
3979 3990
3980 memcpy (this_format, this_format_start, 3991 memcpy (this_format, this_format_start, this_format_len);
3981 format - this_format_start); 3992 this_format[this_format_len] = 0;
3982 this_format[format - this_format_start] = 0;
3983 3993
3984 if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g') 3994 if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g')
3985 sprintf (p, this_format, XFLOAT_DATA (args[n])); 3995 sprintf (p, this_format, XFLOAT_DATA (args[n]));
3986 else 3996 else
3987 { 3997 {
3988 if (sizeof (EMACS_INT) > sizeof (int) 3998 if (pIlen && format[-1] != 'c')
3989 && format[-1] != 'c')
3990 { 3999 {
3991 /* Insert 'l' before format spec. */ 4000 /* Insert pI before format spec. */
3992 this_format[format - this_format_start] 4001 memcpy (&this_format[this_format_len - 1], pI, pIlen);
3993 = this_format[format - this_format_start - 1]; 4002 this_format[this_format_len + pIlen - 1] = format[-1];
3994 this_format[format - this_format_start - 1] = 'l'; 4003 this_format[this_format_len + pIlen] = 0;
3995 this_format[format - this_format_start + 1] = 0;
3996 } 4004 }
3997 4005
3998 if (INTEGERP (args[n])) 4006 if (INTEGERP (args[n]))
@@ -4089,7 +4097,7 @@ usage: (format STRING &rest OBJECTS) */)
4089 if (CONSP (props)) 4097 if (CONSP (props))
4090 { 4098 {
4091 EMACS_INT bytepos = 0, position = 0, translated = 0; 4099 EMACS_INT bytepos = 0, position = 0, translated = 0;
4092 int argn = 1; 4100 EMACS_INT argn = 1;
4093 Lisp_Object list; 4101 Lisp_Object list;
4094 4102
4095 /* Adjust the bounds of each text property 4103 /* Adjust the bounds of each text property