diff options
| author | Paul Eggert | 2014-04-27 18:29:44 -0700 |
|---|---|---|
| committer | Paul Eggert | 2014-04-27 18:29:44 -0700 |
| commit | 6ab1b16c54b63d1c4217b6fcea026400029fcc72 (patch) | |
| tree | e3fef3d5e3f4436b2bc59b1006afc98075da06f0 /src | |
| parent | 196bfaecb0caffcdbb699694139a97148e90e227 (diff) | |
| download | emacs-6ab1b16c54b63d1c4217b6fcea026400029fcc72.tar.gz emacs-6ab1b16c54b63d1c4217b6fcea026400029fcc72.zip | |
Avoid undefined behavior in signed left shift.
This ports to GCC 4.9.0 with -fsanitize=undefined.
* alloc.c (bool_vector_fill, SETMARKBIT, UNSETMARKBIT):
* data.c (Fash):
* regex.c (extract_number):
* lisp.h (make_number, XINT):
Do not shift a 1 bit left into a sign bit.
* alloc.c (struct cons_block, struct float_block): Use unsigned,
not int, for gcmarkbits. All uses changed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 12 | ||||
| -rw-r--r-- | src/alloc.c | 18 | ||||
| -rw-r--r-- | src/data.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 19 | ||||
| -rw-r--r-- | src/regex.c | 3 |
5 files changed, 40 insertions, 14 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 9d4fd2d6d37..90223d6d103 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,15 @@ | |||
| 1 | 2014-04-28 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Avoid undefined behavior in signed left shift. | ||
| 4 | This ports to GCC 4.9.0 with -fsanitize=undefined. | ||
| 5 | * alloc.c (bool_vector_fill, SETMARKBIT, UNSETMARKBIT): | ||
| 6 | * data.c (Fash): | ||
| 7 | * regex.c (extract_number): | ||
| 8 | * lisp.h (make_number, XINT): | ||
| 9 | Do not shift a 1 bit left into a sign bit. | ||
| 10 | * alloc.c (struct cons_block, struct float_block): Use unsigned, | ||
| 11 | not int, for gcmarkbits. All uses changed. | ||
| 12 | |||
| 1 | 2014-04-25 Eli Zaretskii <eliz@gnu.org> | 13 | 2014-04-25 Eli Zaretskii <eliz@gnu.org> |
| 2 | 14 | ||
| 3 | * search.c (Fnewline_cache_check): Don't try to count newlines | 15 | * search.c (Fnewline_cache_check): Don't try to count newlines |
diff --git a/src/alloc.c b/src/alloc.c index 6bee0c990c4..32d3333cea8 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -2131,7 +2131,7 @@ bool_vector_fill (Lisp_Object a, Lisp_Object init) | |||
| 2131 | unsigned char *data = bool_vector_uchar_data (a); | 2131 | unsigned char *data = bool_vector_uchar_data (a); |
| 2132 | int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; | 2132 | int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; |
| 2133 | ptrdiff_t nbytes = bool_vector_bytes (nbits); | 2133 | ptrdiff_t nbytes = bool_vector_bytes (nbits); |
| 2134 | int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); | 2134 | int last_mask = ~ (~0u << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); |
| 2135 | memset (data, pattern, nbytes - 1); | 2135 | memset (data, pattern, nbytes - 1); |
| 2136 | data[nbytes - 1] = pattern & last_mask; | 2136 | data[nbytes - 1] = pattern & last_mask; |
| 2137 | } | 2137 | } |
| @@ -2336,17 +2336,17 @@ make_formatted_string (char *buf, const char *format, ...) | |||
| 2336 | / (sizeof (struct Lisp_Float) * CHAR_BIT + 1)) | 2336 | / (sizeof (struct Lisp_Float) * CHAR_BIT + 1)) |
| 2337 | 2337 | ||
| 2338 | #define GETMARKBIT(block,n) \ | 2338 | #define GETMARKBIT(block,n) \ |
| 2339 | (((block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ | 2339 | (((block)->gcmarkbits[(n) / (sizeof (unsigned) * CHAR_BIT)] \ |
| 2340 | >> ((n) % (sizeof (int) * CHAR_BIT))) \ | 2340 | >> ((n) % (sizeof (unsigned) * CHAR_BIT))) \ |
| 2341 | & 1) | 2341 | & 1) |
| 2342 | 2342 | ||
| 2343 | #define SETMARKBIT(block,n) \ | 2343 | #define SETMARKBIT(block,n) \ |
| 2344 | (block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ | 2344 | ((block)->gcmarkbits[(n) / (sizeof (unsigned) * CHAR_BIT)] \ |
| 2345 | |= 1 << ((n) % (sizeof (int) * CHAR_BIT)) | 2345 | |= 1u << ((n) % (sizeof (unsigned) * CHAR_BIT))) |
| 2346 | 2346 | ||
| 2347 | #define UNSETMARKBIT(block,n) \ | 2347 | #define UNSETMARKBIT(block,n) \ |
| 2348 | (block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \ | 2348 | ((block)->gcmarkbits[(n) / (sizeof (unsigned) * CHAR_BIT)] \ |
| 2349 | &= ~(1 << ((n) % (sizeof (int) * CHAR_BIT))) | 2349 | &= ~(1u << ((n) % (sizeof (unsigned) * CHAR_BIT)))) |
| 2350 | 2350 | ||
| 2351 | #define FLOAT_BLOCK(fptr) \ | 2351 | #define FLOAT_BLOCK(fptr) \ |
| 2352 | ((struct float_block *) (((uintptr_t) (fptr)) & ~(BLOCK_ALIGN - 1))) | 2352 | ((struct float_block *) (((uintptr_t) (fptr)) & ~(BLOCK_ALIGN - 1))) |
| @@ -2358,7 +2358,7 @@ struct float_block | |||
| 2358 | { | 2358 | { |
| 2359 | /* Place `floats' at the beginning, to ease up FLOAT_INDEX's job. */ | 2359 | /* Place `floats' at the beginning, to ease up FLOAT_INDEX's job. */ |
| 2360 | struct Lisp_Float floats[FLOAT_BLOCK_SIZE]; | 2360 | struct Lisp_Float floats[FLOAT_BLOCK_SIZE]; |
| 2361 | int gcmarkbits[1 + FLOAT_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)]; | 2361 | unsigned gcmarkbits[1 + FLOAT_BLOCK_SIZE / (sizeof (unsigned) * CHAR_BIT)]; |
| 2362 | struct float_block *next; | 2362 | struct float_block *next; |
| 2363 | }; | 2363 | }; |
| 2364 | 2364 | ||
| @@ -2452,7 +2452,7 @@ struct cons_block | |||
| 2452 | { | 2452 | { |
| 2453 | /* Place `conses' at the beginning, to ease up CONS_INDEX's job. */ | 2453 | /* Place `conses' at the beginning, to ease up CONS_INDEX's job. */ |
| 2454 | struct Lisp_Cons conses[CONS_BLOCK_SIZE]; | 2454 | struct Lisp_Cons conses[CONS_BLOCK_SIZE]; |
| 2455 | int gcmarkbits[1 + CONS_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)]; | 2455 | unsigned gcmarkbits[1 + CONS_BLOCK_SIZE / (sizeof (unsigned) * CHAR_BIT)]; |
| 2456 | struct cons_block *next; | 2456 | struct cons_block *next; |
| 2457 | }; | 2457 | }; |
| 2458 | 2458 | ||
diff --git a/src/data.c b/src/data.c index 965ddd215f5..bf863aaed79 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2895,7 +2895,7 @@ In this case, the sign bit is duplicated. */) | |||
| 2895 | if (XINT (count) >= BITS_PER_EMACS_INT) | 2895 | if (XINT (count) >= BITS_PER_EMACS_INT) |
| 2896 | XSETINT (val, 0); | 2896 | XSETINT (val, 0); |
| 2897 | else if (XINT (count) > 0) | 2897 | else if (XINT (count) > 0) |
| 2898 | XSETINT (val, XINT (value) << XFASTINT (count)); | 2898 | XSETINT (val, XUINT (value) << XFASTINT (count)); |
| 2899 | else if (XINT (count) <= -BITS_PER_EMACS_INT) | 2899 | else if (XINT (count) <= -BITS_PER_EMACS_INT) |
| 2900 | XSETINT (val, XINT (value) < 0 ? -1 : 0); | 2900 | XSETINT (val, XINT (value) < 0 ? -1 : 0); |
| 2901 | else | 2901 | else |
diff --git a/src/lisp.h b/src/lisp.h index 4c310f69662..5e0f141cc9c 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -354,7 +354,8 @@ error !; | |||
| 354 | # define lisp_h_check_cons_list() ((void) 0) | 354 | # define lisp_h_check_cons_list() ((void) 0) |
| 355 | #endif | 355 | #endif |
| 356 | #if USE_LSB_TAG | 356 | #if USE_LSB_TAG |
| 357 | # define lisp_h_make_number(n) XIL ((EMACS_INT) (n) << INTTYPEBITS) | 357 | # define lisp_h_make_number(n) \ |
| 358 | XIL ((EMACS_INT) ((EMACS_UINT) (n) << INTTYPEBITS)) | ||
| 358 | # define lisp_h_XFASTINT(a) XINT (a) | 359 | # define lisp_h_XFASTINT(a) XINT (a) |
| 359 | # define lisp_h_XINT(a) (XLI (a) >> INTTYPEBITS) | 360 | # define lisp_h_XINT(a) (XLI (a) >> INTTYPEBITS) |
| 360 | # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK)) | 361 | # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK)) |
| @@ -665,7 +666,14 @@ LISP_MACRO_DEFUN (XUNTAG, void *, (Lisp_Object a, int type), (a, type)) | |||
| 665 | INLINE Lisp_Object | 666 | INLINE Lisp_Object |
| 666 | make_number (EMACS_INT n) | 667 | make_number (EMACS_INT n) |
| 667 | { | 668 | { |
| 668 | return XIL (USE_LSB_TAG ? n << INTTYPEBITS : n & INTMASK); | 669 | if (USE_LSB_TAG) |
| 670 | { | ||
| 671 | EMACS_UINT u = n; | ||
| 672 | n = u << INTTYPEBITS; | ||
| 673 | } | ||
| 674 | else | ||
| 675 | n &= INTMASK; | ||
| 676 | return XIL (n); | ||
| 669 | } | 677 | } |
| 670 | 678 | ||
| 671 | /* Extract A's value as a signed integer. */ | 679 | /* Extract A's value as a signed integer. */ |
| @@ -673,7 +681,12 @@ INLINE EMACS_INT | |||
| 673 | XINT (Lisp_Object a) | 681 | XINT (Lisp_Object a) |
| 674 | { | 682 | { |
| 675 | EMACS_INT i = XLI (a); | 683 | EMACS_INT i = XLI (a); |
| 676 | return (USE_LSB_TAG ? i : i << INTTYPEBITS) >> INTTYPEBITS; | 684 | if (! USE_LSB_TAG) |
| 685 | { | ||
| 686 | EMACS_UINT u = i; | ||
| 687 | i = u << INTTYPEBITS; | ||
| 688 | } | ||
| 689 | return i >> INTTYPEBITS; | ||
| 677 | } | 690 | } |
| 678 | 691 | ||
| 679 | /* Like XINT (A), but may be faster. A must be nonnegative. | 692 | /* Like XINT (A), but may be faster. A must be nonnegative. |
diff --git a/src/regex.c b/src/regex.c index 244924058a0..622db708b98 100644 --- a/src/regex.c +++ b/src/regex.c | |||
| @@ -713,7 +713,8 @@ typedef enum | |||
| 713 | static int | 713 | static int |
| 714 | extract_number (re_char *source) | 714 | extract_number (re_char *source) |
| 715 | { | 715 | { |
| 716 | return (SIGN_EXTEND_CHAR (source[1]) << 8) + source[0]; | 716 | unsigned leading_byte = SIGN_EXTEND_CHAR (source[1]); |
| 717 | return (leading_byte << 8) + source[0]; | ||
| 717 | } | 718 | } |
| 718 | 719 | ||
| 719 | /* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. | 720 | /* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. |