aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2011-06-12 17:36:03 -0700
committerPaul Eggert2011-06-12 17:36:03 -0700
commit13bdea59234b227bf8499a64352da3e5fd9e8c7b (patch)
treededdcce496ffa4fdb6d5ffd45ec8c2c7c5c49d0c /src
parentd37ca62316e7526da7d75cc44c7a4cd8a6281bb5 (diff)
downloademacs-13bdea59234b227bf8499a64352da3e5fd9e8c7b.tar.gz
emacs-13bdea59234b227bf8499a64352da3e5fd9e8c7b.zip
Make sure a 64-bit char is never passed to CHAR_STRING.
Otherwise, CHAR_STRING would do the wrong thing on a 64-bit platform, by silently ignoring the top 32 bits, allowing some values that were far too large to be valid characters. * character.h: Include <verify.h>. (CHAR_STRING, CHAR_STRING_ADVANCE): Verify that the character arguments are no wider than unsigned, as a compile-time check to prevent future regressions in this area. * data.c (Faset): * editfns.c (Fchar_to_string, general_insert_function, Finsert_char): (Fsubst_char_in_region): * fns.c (concat): * xdisp.c (decode_mode_spec_coding): Adjust to CHAR_STRING's new requirement. * editfns.c (Finsert_char, Fsubst_char_in_region): * fns.c (concat): Check that character args are actually characters. Without this test, these functions did the wrong thing with wildly out-of-range values on 64-bit hosts.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog22
-rw-r--r--src/character.h9
-rw-r--r--src/data.c4
-rw-r--r--src/editfns.c38
-rw-r--r--src/fns.c9
-rw-r--r--src/xdisp.c3
6 files changed, 61 insertions, 24 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 921f976334a..f8a4abd9cce 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,25 @@
12011-06-13 Paul Eggert <eggert@cs.ucla.edu>
2
3
4 Make sure a 64-bit char is never passed to CHAR_STRING.
5 Otherwise, CHAR_STRING would do the wrong thing on a 64-bit platform,
6 by silently ignoring the top 32 bits, allowing some values
7 that were far too large to be valid characters.
8 * character.h: Include <verify.h>.
9 (CHAR_STRING, CHAR_STRING_ADVANCE): Verify that the character
10 arguments are no wider than unsigned, as a compile-time check
11 to prevent future regressions in this area.
12 * data.c (Faset):
13 * editfns.c (Fchar_to_string, general_insert_function, Finsert_char):
14 (Fsubst_char_in_region):
15 * fns.c (concat):
16 * xdisp.c (decode_mode_spec_coding):
17 Adjust to CHAR_STRING's new requirement.
18 * editfns.c (Finsert_char, Fsubst_char_in_region):
19 * fns.c (concat): Check that character args are actually
20 characters. Without this test, these functions did the wrong
21 thing with wildly out-of-range values on 64-bit hosts.
22
12011-06-12 Paul Eggert <eggert@cs.ucla.edu> 232011-06-12 Paul Eggert <eggert@cs.ucla.edu>
2 24
3 Remove incorrect casts to 'unsigned' that lose info on 64-bit hosts. 25 Remove incorrect casts to 'unsigned' that lose info on 64-bit hosts.
diff --git a/src/character.h b/src/character.h
index 695a55be3fa..de97754cfc7 100644
--- a/src/character.h
+++ b/src/character.h
@@ -23,6 +23,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
23#ifndef EMACS_CHARACTER_H 23#ifndef EMACS_CHARACTER_H
24#define EMACS_CHARACTER_H 24#define EMACS_CHARACTER_H
25 25
26#include <verify.h>
27
26/* character code 1st byte byte sequence 28/* character code 1st byte byte sequence
27 -------------- -------- ------------- 29 -------------- -------- -------------
28 0-7F 00..7F 0xxxxxxx 30 0-7F 00..7F 0xxxxxxx
@@ -173,7 +175,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
173 (p)[1] = (0x80 | (((c) >> 6) & 0x3F)), \ 175 (p)[1] = (0x80 | (((c) >> 6) & 0x3F)), \
174 (p)[2] = (0x80 | ((c) & 0x3F)), \ 176 (p)[2] = (0x80 | ((c) & 0x3F)), \
175 3) \ 177 3) \
176 : char_string ((unsigned) c, p)) 178 : (char_string (c, p) + !verify_true (sizeof (c) <= sizeof (unsigned))))
177 179
178/* Store multibyte form of byte B in P. The caller should allocate at 180/* Store multibyte form of byte B in P. The caller should allocate at
179 least MAX_MULTIBYTE_LENGTH bytes area at P in advance. Returns the 181 least MAX_MULTIBYTE_LENGTH bytes area at P in advance. Returns the
@@ -201,7 +203,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
201 *(p)++ = (0x80 | (((c) >> 6) & 0x3F)), \ 203 *(p)++ = (0x80 | (((c) >> 6) & 0x3F)), \
202 *(p)++ = (0x80 | ((c) & 0x3F)); \ 204 *(p)++ = (0x80 | ((c) & 0x3F)); \
203 else \ 205 else \
204 (p) += char_string ((c), (p)); \ 206 { \
207 verify (sizeof (c) <= sizeof (unsigned)); \
208 (p) += char_string (c, p); \
209 } \
205 } while (0) 210 } while (0)
206 211
207 212
diff --git a/src/data.c b/src/data.c
index 57d7753e393..3a08a7a8cd3 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2152,17 +2152,19 @@ bool-vector. IDX starts at 0. */)
2152 { 2152 {
2153 EMACS_INT idxval_byte, prev_bytes, new_bytes, nbytes; 2153 EMACS_INT idxval_byte, prev_bytes, new_bytes, nbytes;
2154 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1; 2154 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
2155 int c;
2155 2156
2156 if (idxval < 0 || idxval >= SCHARS (array)) 2157 if (idxval < 0 || idxval >= SCHARS (array))
2157 args_out_of_range (array, idx); 2158 args_out_of_range (array, idx);
2158 CHECK_CHARACTER (newelt); 2159 CHECK_CHARACTER (newelt);
2160 c = XFASTINT (newelt);
2159 2161
2160 nbytes = SBYTES (array); 2162 nbytes = SBYTES (array);
2161 2163
2162 idxval_byte = string_char_to_byte (array, idxval); 2164 idxval_byte = string_char_to_byte (array, idxval);
2163 p1 = SDATA (array) + idxval_byte; 2165 p1 = SDATA (array) + idxval_byte;
2164 prev_bytes = BYTES_BY_CHAR_HEAD (*p1); 2166 prev_bytes = BYTES_BY_CHAR_HEAD (*p1);
2165 new_bytes = CHAR_STRING (XINT (newelt), p0); 2167 new_bytes = CHAR_STRING (c, p0);
2166 if (prev_bytes != new_bytes) 2168 if (prev_bytes != new_bytes)
2167 { 2169 {
2168 /* We must relocate the string data. */ 2170 /* We must relocate the string data. */
diff --git a/src/editfns.c b/src/editfns.c
index 232af3595d0..81e5917a800 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -185,12 +185,13 @@ DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
185usage: (char-to-string CHAR) */) 185usage: (char-to-string CHAR) */)
186 (Lisp_Object character) 186 (Lisp_Object character)
187{ 187{
188 int len; 188 int c, len;
189 unsigned char str[MAX_MULTIBYTE_LENGTH]; 189 unsigned char str[MAX_MULTIBYTE_LENGTH];
190 190
191 CHECK_CHARACTER (character); 191 CHECK_CHARACTER (character);
192 c = XFASTINT (character);
192 193
193 len = CHAR_STRING (XFASTINT (character), str); 194 len = CHAR_STRING (c, str);
194 return make_string_from_bytes ((char *) str, 1, len); 195 return make_string_from_bytes ((char *) str, 1, len);
195} 196}
196 197
@@ -2203,16 +2204,17 @@ general_insert_function (void (*insert_func)
2203 val = args[argnum]; 2204 val = args[argnum];
2204 if (CHARACTERP (val)) 2205 if (CHARACTERP (val))
2205 { 2206 {
2207 int c = XFASTINT (val);
2206 unsigned char str[MAX_MULTIBYTE_LENGTH]; 2208 unsigned char str[MAX_MULTIBYTE_LENGTH];
2207 int len; 2209 int len;
2208 2210
2209 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))) 2211 if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
2210 len = CHAR_STRING (XFASTINT (val), str); 2212 len = CHAR_STRING (c, str);
2211 else 2213 else
2212 { 2214 {
2213 str[0] = (ASCII_CHAR_P (XINT (val)) 2215 str[0] = (ASCII_CHAR_P (c)
2214 ? XINT (val) 2216 ? c
2215 : multibyte_char_to_unibyte (XINT (val))); 2217 : multibyte_char_to_unibyte (c));
2216 len = 1; 2218 len = 1;
2217 } 2219 }
2218 (*insert_func) ((char *) str, len); 2220 (*insert_func) ((char *) str, len);
@@ -2332,16 +2334,17 @@ from adjoining text, if those properties are sticky. */)
2332 register EMACS_INT stringlen; 2334 register EMACS_INT stringlen;
2333 register int i; 2335 register int i;
2334 register EMACS_INT n; 2336 register EMACS_INT n;
2335 int len; 2337 int c, len;
2336 unsigned char str[MAX_MULTIBYTE_LENGTH]; 2338 unsigned char str[MAX_MULTIBYTE_LENGTH];
2337 2339
2338 CHECK_NUMBER (character); 2340 CHECK_CHARACTER (character);
2339 CHECK_NUMBER (count); 2341 CHECK_NUMBER (count);
2342 c = XFASTINT (character);
2340 2343
2341 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))) 2344 if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
2342 len = CHAR_STRING (XFASTINT (character), str); 2345 len = CHAR_STRING (c, str);
2343 else 2346 else
2344 str[0] = XFASTINT (character), len = 1; 2347 str[0] = c, len = 1;
2345 if (BUF_BYTES_MAX / len < XINT (count)) 2348 if (BUF_BYTES_MAX / len < XINT (count))
2346 error ("Maximum buffer size would be exceeded"); 2349 error ("Maximum buffer size would be exceeded");
2347 n = XINT (count) * len; 2350 n = XINT (count) * len;
@@ -2784,17 +2787,20 @@ Both characters must have the same length of multi-byte form. */)
2784 int maybe_byte_combining = COMBINING_NO; 2787 int maybe_byte_combining = COMBINING_NO;
2785 EMACS_INT last_changed = 0; 2788 EMACS_INT last_changed = 0;
2786 int multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters)); 2789 int multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
2790 int fromc, toc;
2787 2791
2788 restart: 2792 restart:
2789 2793
2790 validate_region (&start, &end); 2794 validate_region (&start, &end);
2791 CHECK_NUMBER (fromchar); 2795 CHECK_CHARACTER (fromchar);
2792 CHECK_NUMBER (tochar); 2796 CHECK_CHARACTER (tochar);
2797 fromc = XFASTINT (fromchar);
2798 toc = XFASTINT (tochar);
2793 2799
2794 if (multibyte_p) 2800 if (multibyte_p)
2795 { 2801 {
2796 len = CHAR_STRING (XFASTINT (fromchar), fromstr); 2802 len = CHAR_STRING (fromc, fromstr);
2797 if (CHAR_STRING (XFASTINT (tochar), tostr) != len) 2803 if (CHAR_STRING (toc, tostr) != len)
2798 error ("Characters in `subst-char-in-region' have different byte-lengths"); 2804 error ("Characters in `subst-char-in-region' have different byte-lengths");
2799 if (!ASCII_BYTE_P (*tostr)) 2805 if (!ASCII_BYTE_P (*tostr))
2800 { 2806 {
@@ -2811,8 +2817,8 @@ Both characters must have the same length of multi-byte form. */)
2811 else 2817 else
2812 { 2818 {
2813 len = 1; 2819 len = 1;
2814 fromstr[0] = XFASTINT (fromchar); 2820 fromstr[0] = fromc;
2815 tostr[0] = XFASTINT (tochar); 2821 tostr[0] = toc;
2816 } 2822 }
2817 2823
2818 pos = XINT (start); 2824 pos = XINT (start);
diff --git a/src/fns.c b/src/fns.c
index 7a2845741f9..250df728cab 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -679,12 +679,13 @@ concat (size_t nargs, Lisp_Object *args,
679 } 679 }
680 else 680 else
681 { 681 {
682 CHECK_NUMBER (elt); 682 int c;
683 CHECK_CHARACTER (elt);
684 c = XFASTINT (elt);
683 if (some_multibyte) 685 if (some_multibyte)
684 toindex_byte += CHAR_STRING (XINT (elt), 686 toindex_byte += CHAR_STRING (c, SDATA (val) + toindex_byte);
685 SDATA (val) + toindex_byte);
686 else 687 else
687 SSET (val, toindex_byte++, XINT (elt)); 688 SSET (val, toindex_byte++, c);
688 toindex++; 689 toindex++;
689 } 690 }
690 } 691 }
diff --git a/src/xdisp.c b/src/xdisp.c
index 65f6ddd3889..c4956599295 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -19379,7 +19379,8 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_
19379 else if (CHARACTERP (eoltype)) 19379 else if (CHARACTERP (eoltype))
19380 { 19380 {
19381 unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH); 19381 unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
19382 eol_str_len = CHAR_STRING (XINT (eoltype), tmp); 19382 int c = XFASTINT (eoltype);
19383 eol_str_len = CHAR_STRING (c, tmp);
19383 eol_str = tmp; 19384 eol_str = tmp;
19384 } 19385 }
19385 else 19386 else