aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog15
-rw-r--r--src/dispextern.h2
-rw-r--r--src/dispnew.c110
-rw-r--r--src/fns.c11
-rw-r--r--src/lisp.h6
5 files changed, 103 insertions, 41 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 78b3b97b2d7..d7d32e90089 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,20 @@
12011-07-28 Paul Eggert <eggert@cs.ucla.edu> 12011-07-28 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Integer and memory overflow fixes for display code.
4 * dispextern.h (struct glyph_pool.nglyphs): Now ptrdiff_t, not int.
5 * dispnew.c (adjust_glyph_matrix, realloc_glyph_pool, scrolling_window):
6 Check for overflow in size calculations.
7 (line_draw_cost, realloc_glyph_pool, add_row_entry):
8 Don't assume glyph table len fits in int.
9 (struct row_entry.bucket, row_entry_pool_size, row_entry_idx)
10 (row_table_size): Now ptrdiff_t, not int.
11 (scrolling_window): Avoid overflow in size calculations.
12 Don't update size until allocation succeeds.
13 * fns.c (concat): Check for overflow in size calculations.
14 (next_almost_prime): Verify NEXT_ALMOST_PRIME_LIMIT.
15 * lisp.h (RANGED_INTEGERP, TYPE_RANGED_INTEGERP): New macros.
16 (NEXT_ALMOST_PRIME_LIMIT): New constant.
17
3 * composite.c: Integer overflow fixes. 18 * composite.c: Integer overflow fixes.
4 (get_composition_id): Check for overflow in glyph length calculations. 19 (get_composition_id): Check for overflow in glyph length calculations.
5 20
diff --git a/src/dispextern.h b/src/dispextern.h
index 1d7bf5d53ec..70f426f95a6 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -575,7 +575,7 @@ struct glyph_pool
575 struct glyph *glyphs; 575 struct glyph *glyphs;
576 576
577 /* Allocated size of `glyphs'. */ 577 /* Allocated size of `glyphs'. */
578 int nglyphs; 578 ptrdiff_t nglyphs;
579 579
580 /* Number of rows and columns in a matrix. */ 580 /* Number of rows and columns in a matrix. */
581 int nrows, ncolumns; 581 int nrows, ncolumns;
diff --git a/src/dispnew.c b/src/dispnew.c
index b2f416701c3..4cc101d98bf 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -499,7 +499,10 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
499 /* Enlarge MATRIX->rows if necessary. New rows are cleared. */ 499 /* Enlarge MATRIX->rows if necessary. New rows are cleared. */
500 if (matrix->rows_allocated < dim.height) 500 if (matrix->rows_allocated < dim.height)
501 { 501 {
502 ptrdiff_t size = dim.height * sizeof (struct glyph_row); 502 ptrdiff_t size;
503 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph_row) < dim.height)
504 memory_full (SIZE_MAX);
505 size = dim.height * sizeof (struct glyph_row);
503 new_rows = dim.height - matrix->rows_allocated; 506 new_rows = dim.height - matrix->rows_allocated;
504 matrix->rows = (struct glyph_row *) xrealloc (matrix->rows, size); 507 matrix->rows = (struct glyph_row *) xrealloc (matrix->rows, size);
505 memset (matrix->rows + matrix->rows_allocated, 0, 508 memset (matrix->rows + matrix->rows_allocated, 0,
@@ -573,6 +576,9 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
573 struct glyph_row *row = matrix->rows; 576 struct glyph_row *row = matrix->rows;
574 struct glyph_row *end = row + matrix->rows_allocated; 577 struct glyph_row *end = row + matrix->rows_allocated;
575 578
579 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph) < dim.width)
580 memory_full (SIZE_MAX);
581
576 while (row < end) 582 while (row < end)
577 { 583 {
578 row->glyphs[LEFT_MARGIN_AREA] 584 row->glyphs[LEFT_MARGIN_AREA]
@@ -1217,7 +1223,7 @@ line_draw_cost (struct glyph_matrix *matrix, int vpos)
1217 struct glyph *end = beg + row->used[TEXT_AREA]; 1223 struct glyph *end = beg + row->used[TEXT_AREA];
1218 int len; 1224 int len;
1219 Lisp_Object *glyph_table_base = GLYPH_TABLE_BASE; 1225 Lisp_Object *glyph_table_base = GLYPH_TABLE_BASE;
1220 int glyph_table_len = GLYPH_TABLE_LENGTH; 1226 ptrdiff_t glyph_table_len = GLYPH_TABLE_LENGTH;
1221 1227
1222 /* Ignore trailing and leading spaces if we can. */ 1228 /* Ignore trailing and leading spaces if we can. */
1223 if (!FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */ 1229 if (!FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
@@ -1391,31 +1397,26 @@ free_glyph_pool (struct glyph_pool *pool)
1391static int 1397static int
1392realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim) 1398realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim)
1393{ 1399{
1394 int needed; 1400 ptrdiff_t needed;
1395 int changed_p; 1401 int changed_p;
1396 1402
1397 changed_p = (pool->glyphs == 0 1403 changed_p = (pool->glyphs == 0
1398 || matrix_dim.height != pool->nrows 1404 || matrix_dim.height != pool->nrows
1399 || matrix_dim.width != pool->ncolumns); 1405 || matrix_dim.width != pool->ncolumns);
1400 1406
1407 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph) / matrix_dim.width
1408 < matrix_dim.height)
1409 memory_full (SIZE_MAX);
1410
1401 /* Enlarge the glyph pool. */ 1411 /* Enlarge the glyph pool. */
1402 needed = matrix_dim.width * matrix_dim.height; 1412 needed = matrix_dim.width;
1413 needed *= matrix_dim.height;
1403 if (needed > pool->nglyphs) 1414 if (needed > pool->nglyphs)
1404 { 1415 {
1405 ptrdiff_t size = needed * sizeof (struct glyph); 1416 ptrdiff_t size = needed * sizeof (struct glyph);
1406 1417 pool->glyphs = (struct glyph *) xrealloc (pool->glyphs, size);
1407 if (pool->glyphs) 1418 memset (pool->glyphs + pool->nglyphs, 0,
1408 { 1419 size - pool->nglyphs * sizeof (struct glyph));
1409 pool->glyphs = (struct glyph *) xrealloc (pool->glyphs, size);
1410 memset (pool->glyphs + pool->nglyphs, 0,
1411 size - pool->nglyphs * sizeof (struct glyph));
1412 }
1413 else
1414 {
1415 pool->glyphs = (struct glyph *) xmalloc (size);
1416 memset (pool->glyphs, 0, size);
1417 }
1418
1419 pool->nglyphs = needed; 1420 pool->nglyphs = needed;
1420 } 1421 }
1421 1422
@@ -4166,7 +4167,7 @@ struct row_entry
4166 int new_line_number; 4167 int new_line_number;
4167 4168
4168 /* Bucket index of this row_entry in the hash table row_table. */ 4169 /* Bucket index of this row_entry in the hash table row_table. */
4169 int bucket; 4170 ptrdiff_t bucket;
4170 4171
4171 /* The row described by this entry. */ 4172 /* The row described by this entry. */
4172 struct glyph_row *row; 4173 struct glyph_row *row;
@@ -4180,18 +4181,18 @@ struct row_entry
4180 that we need a larger one. */ 4181 that we need a larger one. */
4181 4182
4182static struct row_entry *row_entry_pool; 4183static struct row_entry *row_entry_pool;
4183static int row_entry_pool_size; 4184static ptrdiff_t row_entry_pool_size;
4184 4185
4185/* Index of next free entry in row_entry_pool. */ 4186/* Index of next free entry in row_entry_pool. */
4186 4187
4187static int row_entry_idx; 4188static ptrdiff_t row_entry_idx;
4188 4189
4189/* The hash table used during scrolling, and the table's size. This 4190/* The hash table used during scrolling, and the table's size. This
4190 table is used to quickly identify equal rows in the desired and 4191 table is used to quickly identify equal rows in the desired and
4191 current matrix. */ 4192 current matrix. */
4192 4193
4193static struct row_entry **row_table; 4194static struct row_entry **row_table;
4194static int row_table_size; 4195static ptrdiff_t row_table_size;
4195 4196
4196/* Vectors of pointers to row_entry structures belonging to the 4197/* Vectors of pointers to row_entry structures belonging to the
4197 current and desired matrix, and the size of the vectors. */ 4198 current and desired matrix, and the size of the vectors. */
@@ -4214,7 +4215,7 @@ static inline struct row_entry *
4214add_row_entry (struct glyph_row *row) 4215add_row_entry (struct glyph_row *row)
4215{ 4216{
4216 struct row_entry *entry; 4217 struct row_entry *entry;
4217 int i = row->hash % row_table_size; 4218 ptrdiff_t i = row->hash % row_table_size;
4218 4219
4219 entry = row_table[i]; 4220 entry = row_table[i];
4220 while (entry && !row_equal_p (entry->row, row, 1)) 4221 while (entry && !row_equal_p (entry->row, row, 1))
@@ -4267,9 +4268,10 @@ scrolling_window (struct window *w, int header_line_p)
4267 struct glyph_matrix *desired_matrix = w->desired_matrix; 4268 struct glyph_matrix *desired_matrix = w->desired_matrix;
4268 struct glyph_matrix *current_matrix = w->current_matrix; 4269 struct glyph_matrix *current_matrix = w->current_matrix;
4269 int yb = window_text_bottom_y (w); 4270 int yb = window_text_bottom_y (w);
4270 int i, j, first_old, first_new, last_old, last_new; 4271 ptrdiff_t i;
4271 int nruns, n, run_idx; 4272 int j, first_old, first_new, last_old, last_new;
4272 ptrdiff_t nbytes; 4273 int nruns, run_idx;
4274 ptrdiff_t n, nbytes;
4273 struct row_entry *entry; 4275 struct row_entry *entry;
4274 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); 4276 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
4275 4277
@@ -4354,45 +4356,77 @@ scrolling_window (struct window *w, int header_line_p)
4354 if (last_new == first_new) 4356 if (last_new == first_new)
4355 return 0; 4357 return 0;
4356 4358
4359 /* Check for integer overflow in xrealloc size calculation.
4360
4361 If next_almost_prime checks (N) for divisibility by 2..10, then
4362 it can return at most N + 10, e.g., next_almost_prime (1) == 11.
4363 So, set next_almost_prime_increment_max to 10.
4364
4365 It's just a coincidence that next_almost_prime_increment_max ==
4366 NEXT_ALMOST_PRIME_LIMIT - 1. If NEXT_ALMOST_PRIME_LIMIT were
4367 13, then next_almost_prime_increment_max would be 14, e.g.,
4368 because next_almost_prime (113) would be 127. */
4369 {
4370 verify (NEXT_ALMOST_PRIME_LIMIT == 11);
4371 enum { next_almost_prime_increment_max = 10 };
4372 ptrdiff_t alloc_max = min (PTRDIFF_MAX, SIZE_MAX);
4373 ptrdiff_t row_table_max =
4374 ((alloc_max - next_almost_prime_increment_max)
4375 / (3 * sizeof *row_table));
4376 ptrdiff_t row_entry_pool_max = alloc_max / sizeof *row_entry_pool;
4377 int n_max = min (INT_MAX, min (row_table_max, row_entry_pool_max));
4378 ptrdiff_t old_lines_max = alloc_max / sizeof *old_lines;
4379 int current_nrows_max = min (n_max - desired_matrix->nrows, old_lines_max);
4380 int desired_nrows_max =
4381 min (INT_MAX,
4382 alloc_max / max (sizeof *new_lines,
4383 max (sizeof *runs, sizeof *run_pool)));
4384 if (current_nrows_max < current_matrix->nrows
4385 || desired_nrows_max < desired_matrix->nrows)
4386 memory_full (SIZE_MAX);
4387 }
4388
4357 /* Reallocate vectors, tables etc. if necessary. */ 4389 /* Reallocate vectors, tables etc. if necessary. */
4358 4390
4359 if (current_matrix->nrows > old_lines_size) 4391 if (current_matrix->nrows > old_lines_size)
4360 { 4392 {
4361 old_lines_size = current_matrix->nrows; 4393 nbytes = current_matrix->nrows * sizeof *old_lines;
4362 nbytes = old_lines_size * sizeof *old_lines;
4363 old_lines = (struct row_entry **) xrealloc (old_lines, nbytes); 4394 old_lines = (struct row_entry **) xrealloc (old_lines, nbytes);
4395 old_lines_size = current_matrix->nrows;
4364 } 4396 }
4365 4397
4366 if (desired_matrix->nrows > new_lines_size) 4398 if (desired_matrix->nrows > new_lines_size)
4367 { 4399 {
4368 new_lines_size = desired_matrix->nrows; 4400 nbytes = desired_matrix->nrows * sizeof *new_lines;
4369 nbytes = new_lines_size * sizeof *new_lines;
4370 new_lines = (struct row_entry **) xrealloc (new_lines, nbytes); 4401 new_lines = (struct row_entry **) xrealloc (new_lines, nbytes);
4402 new_lines_size = desired_matrix->nrows;
4371 } 4403 }
4372 4404
4373 n = desired_matrix->nrows + current_matrix->nrows; 4405 n = desired_matrix->nrows;
4374 if (3 * n > row_table_size) 4406 n += current_matrix->nrows;
4407 if (row_table_size / 3 < n)
4375 { 4408 {
4376 row_table_size = next_almost_prime (3 * n); 4409 ptrdiff_t size = next_almost_prime (3 * n);
4377 nbytes = row_table_size * sizeof *row_table; 4410 nbytes = size * sizeof *row_table;
4378 row_table = (struct row_entry **) xrealloc (row_table, nbytes); 4411 row_table = (struct row_entry **) xrealloc (row_table, nbytes);
4412 row_table_size = size;
4379 memset (row_table, 0, nbytes); 4413 memset (row_table, 0, nbytes);
4380 } 4414 }
4381 4415
4382 if (n > row_entry_pool_size) 4416 if (n > row_entry_pool_size)
4383 { 4417 {
4384 row_entry_pool_size = n; 4418 nbytes = n * sizeof *row_entry_pool;
4385 nbytes = row_entry_pool_size * sizeof *row_entry_pool;
4386 row_entry_pool = (struct row_entry *) xrealloc (row_entry_pool, nbytes); 4419 row_entry_pool = (struct row_entry *) xrealloc (row_entry_pool, nbytes);
4420 row_entry_pool_size = n;
4387 } 4421 }
4388 4422
4389 if (desired_matrix->nrows > runs_size) 4423 if (desired_matrix->nrows > runs_size)
4390 { 4424 {
4391 runs_size = desired_matrix->nrows; 4425 nbytes = desired_matrix->nrows * sizeof *runs;
4392 nbytes = runs_size * sizeof *runs;
4393 runs = (struct run **) xrealloc (runs, nbytes); 4426 runs = (struct run **) xrealloc (runs, nbytes);
4394 nbytes = runs_size * sizeof *run_pool; 4427 nbytes = desired_matrix->nrows * sizeof *run_pool;
4395 run_pool = (struct run *) xrealloc (run_pool, nbytes); 4428 run_pool = (struct run *) xrealloc (run_pool, nbytes);
4429 runs_size = desired_matrix->nrows;
4396 } 4430 }
4397 4431
4398 nruns = run_idx = 0; 4432 nruns = run_idx = 0;
diff --git a/src/fns.c b/src/fns.c
index fdaffe947ac..e5538d6acbc 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -602,7 +602,12 @@ concat (ptrdiff_t nargs, Lisp_Object *args,
602 602
603 prev = Qnil; 603 prev = Qnil;
604 if (STRINGP (val)) 604 if (STRINGP (val))
605 SAFE_ALLOCA (textprops, struct textprop_rec *, sizeof (struct textprop_rec) * nargs); 605 {
606 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *textprops < nargs)
607 memory_full (SIZE_MAX);
608 SAFE_ALLOCA (textprops, struct textprop_rec *,
609 sizeof *textprops * nargs);
610 }
606 611
607 for (argnum = 0; argnum < nargs; argnum++) 612 for (argnum = 0; argnum < nargs; argnum++)
608 { 613 {
@@ -3395,11 +3400,13 @@ check_hash_table (Lisp_Object obj)
3395 3400
3396 3401
3397/* Value is the next integer I >= N, N >= 0 which is "almost" a prime 3402/* Value is the next integer I >= N, N >= 0 which is "almost" a prime
3398 number. */ 3403 number. A number is "almost" a prime number if it is not divisible
3404 by any integer in the range 2 .. (NEXT_ALMOST_PRIME_LIMIT - 1). */
3399 3405
3400EMACS_INT 3406EMACS_INT
3401next_almost_prime (EMACS_INT n) 3407next_almost_prime (EMACS_INT n)
3402{ 3408{
3409 verify (NEXT_ALMOST_PRIME_LIMIT == 11);
3403 for (n |= 1; ; n += 2) 3410 for (n |= 1; ; n += 2)
3404 if (n % 3 != 0 && n % 5 != 0 && n % 7 != 0) 3411 if (n % 3 != 0 && n % 5 != 0 && n % 7 != 0)
3405 return n; 3412 return n;
diff --git a/src/lisp.h b/src/lisp.h
index 2d326043614..267bfe1b21f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1704,6 +1704,11 @@ typedef struct {
1704#define NUMBERP(x) (INTEGERP (x) || FLOATP (x)) 1704#define NUMBERP(x) (INTEGERP (x) || FLOATP (x))
1705#define NATNUMP(x) (INTEGERP (x) && XINT (x) >= 0) 1705#define NATNUMP(x) (INTEGERP (x) && XINT (x) >= 0)
1706 1706
1707#define RANGED_INTEGERP(lo, x, hi) \
1708 (INTEGERP (x) && (lo) <= XINT (x) && XINT (x) <= (hi))
1709#define TYPE_RANGED_INTEGERP(type, x) \
1710 RANGED_INTEGERP (TYPE_MINIMUM (type), x, TYPE_MAXIMUM (type))
1711
1707#define INTEGERP(x) (LISP_INT_TAG_P (XTYPE ((x)))) 1712#define INTEGERP(x) (LISP_INT_TAG_P (XTYPE ((x))))
1708#define SYMBOLP(x) (XTYPE ((x)) == Lisp_Symbol) 1713#define SYMBOLP(x) (XTYPE ((x)) == Lisp_Symbol)
1709#define MISCP(x) (XTYPE ((x)) == Lisp_Misc) 1714#define MISCP(x) (XTYPE ((x)) == Lisp_Misc)
@@ -2551,6 +2556,7 @@ extern void syms_of_syntax (void);
2551 2556
2552/* Defined in fns.c */ 2557/* Defined in fns.c */
2553extern Lisp_Object QCrehash_size, QCrehash_threshold; 2558extern Lisp_Object QCrehash_size, QCrehash_threshold;
2559enum { NEXT_ALMOST_PRIME_LIMIT = 11 };
2554extern EMACS_INT next_almost_prime (EMACS_INT); 2560extern EMACS_INT next_almost_prime (EMACS_INT);
2555extern Lisp_Object larger_vector (Lisp_Object, EMACS_INT, Lisp_Object); 2561extern Lisp_Object larger_vector (Lisp_Object, EMACS_INT, Lisp_Object);
2556extern void sweep_weak_hash_tables (void); 2562extern void sweep_weak_hash_tables (void);