diff options
| author | Paul Eggert | 2024-07-20 15:52:05 -0700 |
|---|---|---|
| committer | Paul Eggert | 2024-07-20 16:16:22 -0700 |
| commit | 515e5ad0de133f0a3d501bd6290ccc51d8462955 (patch) | |
| tree | 620ff4a699eab76b3bcb441b5507b87854f00097 /src/alloc.c | |
| parent | 76497a01425e19a6c3a02c1e3031061fa0e7885b (diff) | |
| download | emacs-515e5ad0de133f0a3d501bd6290ccc51d8462955.tar.gz emacs-515e5ad0de133f0a3d501bd6290ccc51d8462955.zip | |
Fix bool vector length overflow
* src/alloc.c (make_clear_bool_vector): It’s now the caller’s
responsibility to make sure the bool vector length is in range.
Add an eassert to double-check this. This lets some locals be
ptrdiff_t not EMACS_INT.
(Fmake_bool_vector, Fbool_vector):
Check that bool vector lengths are in range.
* src/lisp.h (BOOL_VECTOR_LENGTH_MAX): New macro.
(bool_vector_words, bool_vector_bytes): Avoid undefined
behavior if size == EMACS_INT_MAX - (BITS_PER_BITS_WORD - 1).
This is mostly theoretical but it’s easy to do it right.
* src/lread.c (read_bool_vector): Use EMACS_INT, not just ptrdiff_t.
Check that length doesn’t exceed BOOL_VECTOR_LENGTH_MAX.
This fixes an unlikely integer overflow where the calculated size
went negative.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/src/alloc.c b/src/alloc.c index 41679b52707..48b170b866f 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -2413,14 +2413,13 @@ bool_vector_fill (Lisp_Object a, Lisp_Object init) | |||
| 2413 | Lisp_Object | 2413 | Lisp_Object |
| 2414 | make_clear_bool_vector (EMACS_INT nbits, bool clearit) | 2414 | make_clear_bool_vector (EMACS_INT nbits, bool clearit) |
| 2415 | { | 2415 | { |
| 2416 | eassert (0 <= nbits && nbits <= BOOL_VECTOR_LENGTH_MAX); | ||
| 2416 | Lisp_Object val; | 2417 | Lisp_Object val; |
| 2417 | EMACS_INT words = bool_vector_words (nbits); | 2418 | ptrdiff_t words = bool_vector_words (nbits); |
| 2418 | EMACS_INT word_bytes = words * sizeof (bits_word); | 2419 | ptrdiff_t word_bytes = words * sizeof (bits_word); |
| 2419 | EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes | 2420 | ptrdiff_t needed_elements = ((bool_header_size - header_size + word_bytes |
| 2420 | + word_size - 1) | 2421 | + word_size - 1) |
| 2421 | / word_size); | 2422 | / word_size); |
| 2422 | if (PTRDIFF_MAX < needed_elements) | ||
| 2423 | memory_full (SIZE_MAX); | ||
| 2424 | struct Lisp_Bool_Vector *p | 2423 | struct Lisp_Bool_Vector *p |
| 2425 | = (struct Lisp_Bool_Vector *) allocate_clear_vector (needed_elements, | 2424 | = (struct Lisp_Bool_Vector *) allocate_clear_vector (needed_elements, |
| 2426 | clearit); | 2425 | clearit); |
| @@ -2449,7 +2448,10 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2449 | (Lisp_Object length, Lisp_Object init) | 2448 | (Lisp_Object length, Lisp_Object init) |
| 2450 | { | 2449 | { |
| 2451 | CHECK_FIXNAT (length); | 2450 | CHECK_FIXNAT (length); |
| 2452 | Lisp_Object val = make_clear_bool_vector (XFIXNAT (length), NILP (init)); | 2451 | EMACS_INT len = XFIXNAT (length); |
| 2452 | if (BOOL_VECTOR_LENGTH_MAX < len) | ||
| 2453 | memory_full (SIZE_MAX); | ||
| 2454 | Lisp_Object val = make_clear_bool_vector (len, NILP (init)); | ||
| 2453 | return NILP (init) ? val : bool_vector_fill (val, init); | 2455 | return NILP (init) ? val : bool_vector_fill (val, init); |
| 2454 | } | 2456 | } |
| 2455 | 2457 | ||
| @@ -2459,6 +2461,8 @@ Allows any number of arguments, including zero. | |||
| 2459 | usage: (bool-vector &rest OBJECTS) */) | 2461 | usage: (bool-vector &rest OBJECTS) */) |
| 2460 | (ptrdiff_t nargs, Lisp_Object *args) | 2462 | (ptrdiff_t nargs, Lisp_Object *args) |
| 2461 | { | 2463 | { |
| 2464 | if (BOOL_VECTOR_LENGTH_MAX < nargs) | ||
| 2465 | memory_full (SIZE_MAX); | ||
| 2462 | Lisp_Object vector = make_clear_bool_vector (nargs, true); | 2466 | Lisp_Object vector = make_clear_bool_vector (nargs, true); |
| 2463 | for (ptrdiff_t i = 0; i < nargs; i++) | 2467 | for (ptrdiff_t i = 0; i < nargs; i++) |
| 2464 | if (!NILP (args[i])) | 2468 | if (!NILP (args[i])) |