Commit 39e378da authored by Paul Eggert's avatar Paul Eggert

* bidi.c: Integer size and overflow fixes.

(bidi_cache_size, bidi_cache_idx, bidi_cache_last_idx)
(bidi_cache_start, bidi_cache_fetch_state, bidi_cache_search)
(bidi_cache_find_level_change, bidi_cache_ensure_space)
(bidi_cache_iterator_state, bidi_cache_find, bidi_cache_start_stack)
(bidi_find_other_level_edge):
Use ptrdiff_t instead of EMACS_INT where either will do.
This works better on 32-bit hosts configured --with-wide-int.
(bidi_cache_ensure_space): Check for size-calculation overflow.
Use % rather than repeated addition, for better worst-case speed.
Don't set bidi_cache_size until after xrealloc returns, because it
might not return.
(bidi_dump_cached_states): Use ptrdiff_t, not int, to avoid overflow.
parent 3f86c085
...@@ -2,6 +2,20 @@ ...@@ -2,6 +2,20 @@
Integer signedness and overflow and related fixes. (Bug#9079) Integer signedness and overflow and related fixes. (Bug#9079)
* bidi.c: Integer size and overflow fixes.
(bidi_cache_size, bidi_cache_idx, bidi_cache_last_idx)
(bidi_cache_start, bidi_cache_fetch_state, bidi_cache_search)
(bidi_cache_find_level_change, bidi_cache_ensure_space)
(bidi_cache_iterator_state, bidi_cache_find, bidi_cache_start_stack)
(bidi_find_other_level_edge):
Use ptrdiff_t instead of EMACS_INT where either will do.
This works better on 32-bit hosts configured --with-wide-int.
(bidi_cache_ensure_space): Check for size-calculation overflow.
Use % rather than repeated addition, for better worst-case speed.
Don't set bidi_cache_size until after xrealloc returns, because it
might not return.
(bidi_dump_cached_states): Use ptrdiff_t, not int, to avoid overflow.
* alloc.c (__malloc_size_t): Remove. * alloc.c (__malloc_size_t): Remove.
All uses replaced by size_t. See Andreas Schwab's note All uses replaced by size_t. See Andreas Schwab's note
<http://debbugs.gnu.org/cgi/bugreport.cgi?bug=9079#8>. <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=9079#8>.
......
...@@ -299,11 +299,11 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from) ...@@ -299,11 +299,11 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from)
#define BIDI_CACHE_CHUNK 200 #define BIDI_CACHE_CHUNK 200
static struct bidi_it *bidi_cache; static struct bidi_it *bidi_cache;
static EMACS_INT bidi_cache_size = 0; static ptrdiff_t bidi_cache_size = 0;
enum { elsz = sizeof (struct bidi_it) }; enum { elsz = sizeof (struct bidi_it) };
static EMACS_INT bidi_cache_idx; /* next unused cache slot */ static ptrdiff_t bidi_cache_idx; /* next unused cache slot */
static EMACS_INT bidi_cache_last_idx; /* slot of last cache hit */ static ptrdiff_t bidi_cache_last_idx; /* slot of last cache hit */
static EMACS_INT bidi_cache_start = 0; /* start of cache for this static ptrdiff_t bidi_cache_start = 0; /* start of cache for this
"stack" level */ "stack" level */
/* Reset the cache state to the empty state. We only reset the part /* Reset the cache state to the empty state. We only reset the part
...@@ -336,7 +336,7 @@ bidi_cache_shrink (void) ...@@ -336,7 +336,7 @@ bidi_cache_shrink (void)
} }
static inline void static inline void
bidi_cache_fetch_state (EMACS_INT idx, struct bidi_it *bidi_it) bidi_cache_fetch_state (ptrdiff_t idx, struct bidi_it *bidi_it)
{ {
int current_scan_dir = bidi_it->scan_dir; int current_scan_dir = bidi_it->scan_dir;
...@@ -352,10 +352,10 @@ bidi_cache_fetch_state (EMACS_INT idx, struct bidi_it *bidi_it) ...@@ -352,10 +352,10 @@ bidi_cache_fetch_state (EMACS_INT idx, struct bidi_it *bidi_it)
level less or equal to LEVEL. if LEVEL is -1, disregard the level less or equal to LEVEL. if LEVEL is -1, disregard the
resolved levels in cached states. DIR, if non-zero, means search resolved levels in cached states. DIR, if non-zero, means search
in that direction from the last cache hit. */ in that direction from the last cache hit. */
static inline EMACS_INT static inline ptrdiff_t
bidi_cache_search (EMACS_INT charpos, int level, int dir) bidi_cache_search (EMACS_INT charpos, int level, int dir)
{ {
EMACS_INT i, i_start; ptrdiff_t i, i_start;
if (bidi_cache_idx > bidi_cache_start) if (bidi_cache_idx > bidi_cache_start)
{ {
...@@ -417,12 +417,12 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir) ...@@ -417,12 +417,12 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir)
C, searching backwards (DIR = -1) for LEVEL = 2 will return the C, searching backwards (DIR = -1) for LEVEL = 2 will return the
index of slot B or A, depending whether BEFORE is, respectively, index of slot B or A, depending whether BEFORE is, respectively,
non-zero or zero. */ non-zero or zero. */
static EMACS_INT static ptrdiff_t
bidi_cache_find_level_change (int level, int dir, int before) bidi_cache_find_level_change (int level, int dir, int before)
{ {
if (bidi_cache_idx) if (bidi_cache_idx)
{ {
EMACS_INT i = dir ? bidi_cache_last_idx : bidi_cache_idx - 1; ptrdiff_t i = dir ? bidi_cache_last_idx : bidi_cache_idx - 1;
int incr = before ? 1 : 0; int incr = before ? 1 : 0;
xassert (!dir || bidi_cache_last_idx >= 0); xassert (!dir || bidi_cache_last_idx >= 0);
...@@ -458,22 +458,26 @@ bidi_cache_find_level_change (int level, int dir, int before) ...@@ -458,22 +458,26 @@ bidi_cache_find_level_change (int level, int dir, int before)
} }
static inline void static inline void
bidi_cache_ensure_space (EMACS_INT idx) bidi_cache_ensure_space (ptrdiff_t idx)
{ {
/* Enlarge the cache as needed. */ /* Enlarge the cache as needed. */
if (idx >= bidi_cache_size) if (idx >= bidi_cache_size)
{ {
while (idx >= bidi_cache_size) ptrdiff_t new_size;
bidi_cache_size += BIDI_CACHE_CHUNK; ptrdiff_t max_size =
bidi_cache = min (PTRDIFF_MAX, SIZE_MAX) / elsz / BIDI_CACHE_CHUNK * BIDI_CACHE_CHUNK;
(struct bidi_it *) xrealloc (bidi_cache, bidi_cache_size * elsz); if (max_size <= idx)
memory_full (SIZE_MAX);
new_size = idx - idx % BIDI_CACHE_CHUNK + BIDI_CACHE_CHUNK;
bidi_cache = (struct bidi_it *) xrealloc (bidi_cache, new_size * elsz);
bidi_cache_size = new_size;
} }
} }
static inline void static inline void
bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved) bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved)
{ {
EMACS_INT idx; ptrdiff_t idx;
/* We should never cache on backward scans. */ /* We should never cache on backward scans. */
if (bidi_it->scan_dir == -1) if (bidi_it->scan_dir == -1)
...@@ -528,7 +532,7 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved) ...@@ -528,7 +532,7 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved)
static inline bidi_type_t static inline bidi_type_t
bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it) bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it)
{ {
EMACS_INT i = bidi_cache_search (charpos, level, bidi_it->scan_dir); ptrdiff_t i = bidi_cache_search (charpos, level, bidi_it->scan_dir);
if (i >= bidi_cache_start) if (i >= bidi_cache_start)
{ {
...@@ -560,7 +564,7 @@ bidi_peek_at_next_level (struct bidi_it *bidi_it) ...@@ -560,7 +564,7 @@ bidi_peek_at_next_level (struct bidi_it *bidi_it)
/* 5-slot stack for saving the start of the previous level of the /* 5-slot stack for saving the start of the previous level of the
cache. xdisp.c maintains a 5-slot stack for its iterator state, cache. xdisp.c maintains a 5-slot stack for its iterator state,
and we need the same size of our stack. */ and we need the same size of our stack. */
static EMACS_INT bidi_cache_start_stack[IT_STACK_SIZE]; static ptrdiff_t bidi_cache_start_stack[IT_STACK_SIZE];
static int bidi_cache_sp; static int bidi_cache_sp;
/* Push the bidi iterator state in preparation for reordering a /* Push the bidi iterator state in preparation for reordering a
...@@ -2123,7 +2127,7 @@ static void ...@@ -2123,7 +2127,7 @@ static void
bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, int end_flag) bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, int end_flag)
{ {
int dir = end_flag ? -bidi_it->scan_dir : bidi_it->scan_dir; int dir = end_flag ? -bidi_it->scan_dir : bidi_it->scan_dir;
EMACS_INT idx; ptrdiff_t idx;
/* Try the cache first. */ /* Try the cache first. */
if ((idx = bidi_cache_find_level_change (level, dir, end_flag)) if ((idx = bidi_cache_find_level_change (level, dir, end_flag))
...@@ -2300,7 +2304,7 @@ void bidi_dump_cached_states (void) EXTERNALLY_VISIBLE; ...@@ -2300,7 +2304,7 @@ void bidi_dump_cached_states (void) EXTERNALLY_VISIBLE;
void void
bidi_dump_cached_states (void) bidi_dump_cached_states (void)
{ {
int i; ptrdiff_t i;
int ndigits = 1; int ndigits = 1;
if (bidi_cache_idx == 0) if (bidi_cache_idx == 0)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment