diff options
| author | Paul Eggert | 2011-07-28 18:49:31 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-07-28 18:49:31 -0700 |
| commit | 8fbadbe3d240897b2fb265e749cfc9bdeb4bac39 (patch) | |
| tree | 695368909c048e89d2cf94fa35c392667d196ab3 /src/tparam.c | |
| parent | 0d8f2df7c41d8904df693e4046849751adebd8ab (diff) | |
| download | emacs-8fbadbe3d240897b2fb265e749cfc9bdeb4bac39.tar.gz emacs-8fbadbe3d240897b2fb265e749cfc9bdeb4bac39.zip | |
* tparam.c: Integer and memory overflow fixes.
(tparam1): Use ptrdiff_t, not int, for sizes.
Don't update size until alloc done.
Redo size calculations to avoid overflow.
Check for size calculation overflow.
Diffstat (limited to 'src/tparam.c')
| -rw-r--r-- | src/tparam.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/src/tparam.c b/src/tparam.c index ed28cd7397f..06cec873153 100644 --- a/src/tparam.c +++ b/src/tparam.c | |||
| @@ -79,33 +79,38 @@ tparam1 (const char *string, char *outstring, int len, | |||
| 79 | register const char *p = string; | 79 | register const char *p = string; |
| 80 | register char *op = outstring; | 80 | register char *op = outstring; |
| 81 | char *outend; | 81 | char *outend; |
| 82 | int outlen = 0; | 82 | char *new = 0; |
| 83 | ptrdiff_t outlen = 0; | ||
| 83 | 84 | ||
| 84 | register int tem; | 85 | register int tem; |
| 85 | int *old_argp = argp; /* can move */ | 86 | int *old_argp = argp; /* can move */ |
| 86 | int *fixed_argp = argp; /* never moves */ | 87 | int *fixed_argp = argp; /* never moves */ |
| 87 | int explicit_param_p = 0; /* set by %p */ | 88 | int explicit_param_p = 0; /* set by %p */ |
| 88 | int doleft = 0; | 89 | ptrdiff_t doleft = 0; |
| 89 | int doup = 0; | 90 | ptrdiff_t doup = 0; |
| 91 | ptrdiff_t append_len = 0; | ||
| 90 | 92 | ||
| 91 | outend = outstring + len; | 93 | outend = outstring + len; |
| 92 | 94 | ||
| 93 | while (1) | 95 | while (1) |
| 94 | { | 96 | { |
| 95 | /* If the buffer might be too short, make it bigger. */ | 97 | /* If the buffer might be too short, make it bigger. */ |
| 96 | if (op + 5 >= outend) | 98 | while (outend - op - append_len <= 5) |
| 97 | { | 99 | { |
| 98 | register char *new; | 100 | ptrdiff_t offset = op - outstring; |
| 99 | int offset = op - outstring; | ||
| 100 | 101 | ||
| 101 | if (outlen == 0) | 102 | if (outlen == 0) |
| 102 | { | 103 | { |
| 104 | if (min (PTRDIFF_MAX, SIZE_MAX) - 40 < len) | ||
| 105 | goto out_of_memory; | ||
| 103 | outlen = len + 40; | 106 | outlen = len + 40; |
| 104 | new = (char *) xmalloc (outlen); | 107 | new = (char *) xmalloc (outlen); |
| 105 | memcpy (new, outstring, offset); | 108 | memcpy (new, outstring, offset); |
| 106 | } | 109 | } |
| 107 | else | 110 | else |
| 108 | { | 111 | { |
| 112 | if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < outlen) | ||
| 113 | goto out_of_memory; | ||
| 109 | outlen *= 2; | 114 | outlen *= 2; |
| 110 | new = (char *) xrealloc (outstring, outlen); | 115 | new = (char *) xrealloc (outstring, outlen); |
| 111 | } | 116 | } |
| @@ -167,11 +172,19 @@ tparam1 (const char *string, char *outstring, int len, | |||
| 167 | and this is one of them, increment it. */ | 172 | and this is one of them, increment it. */ |
| 168 | while (tem == 0 || tem == '\n' || tem == '\t') | 173 | while (tem == 0 || tem == '\n' || tem == '\t') |
| 169 | { | 174 | { |
| 175 | ptrdiff_t append_len_incr; | ||
| 170 | tem++; | 176 | tem++; |
| 171 | if (argp == old_argp) | 177 | if (argp == old_argp) |
| 172 | doup++, outend -= strlen (up); | 178 | doup++, append_len_incr = strlen (up); |
| 173 | else | 179 | else |
| 174 | doleft++, outend -= strlen (left); | 180 | doleft++, append_len_incr = strlen (left); |
| 181 | if (PTRDIFF_MAX - append_len < append_len_incr) | ||
| 182 | { | ||
| 183 | out_of_memory: | ||
| 184 | xfree (new); | ||
| 185 | memory_full (SIZE_MAX); | ||
| 186 | } | ||
| 187 | append_len += append_len_incr; | ||
| 175 | } | 188 | } |
| 176 | } | 189 | } |
| 177 | *op++ = tem ? tem : 0200; | 190 | *op++ = tem ? tem : 0200; |