diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 355 | ||||
-rw-r--r-- | src/bidi.c | 30 | ||||
-rw-r--r-- | src/buffer.c | 21 | ||||
-rw-r--r-- | src/callproc.c | 4 | ||||
-rw-r--r-- | src/category.c | 2 | ||||
-rw-r--r-- | src/ccl.c | 39 | ||||
-rw-r--r-- | src/character.c | 10 | ||||
-rw-r--r-- | src/character.h | 22 | ||||
-rw-r--r-- | src/charset.c | 55 | ||||
-rw-r--r-- | src/charset.h | 4 | ||||
-rw-r--r-- | src/coding.c | 17 | ||||
-rw-r--r-- | src/coding.h | 2 | ||||
-rw-r--r-- | src/composite.c | 60 | ||||
-rw-r--r-- | src/composite.h | 10 | ||||
-rw-r--r-- | src/dispextern.h | 22 | ||||
-rw-r--r-- | src/dispnew.c | 110 | ||||
-rw-r--r-- | src/doc.c | 37 | ||||
-rw-r--r-- | src/editfns.c | 8 | ||||
-rw-r--r-- | src/emacs.c | 15 | ||||
-rw-r--r-- | src/eval.c | 26 | ||||
-rw-r--r-- | src/fileio.c | 6 | ||||
-rw-r--r-- | src/fns.c | 23 | ||||
-rw-r--r-- | src/frame.c | 38 | ||||
-rw-r--r-- | src/frame.h | 4 | ||||
-rw-r--r-- | src/fringe.c | 13 | ||||
-rw-r--r-- | src/ftfont.c | 15 | ||||
-rw-r--r-- | src/gtkutil.c | 39 | ||||
-rw-r--r-- | src/gtkutil.h | 7 | ||||
-rw-r--r-- | src/image.c | 239 | ||||
-rw-r--r-- | src/indent.c | 23 | ||||
-rw-r--r-- | src/keyboard.c | 101 | ||||
-rw-r--r-- | src/keyboard.h | 2 | ||||
-rw-r--r-- | src/keymap.c | 15 | ||||
-rw-r--r-- | src/keymap.h | 2 | ||||
-rw-r--r-- | src/lisp.h | 10 | ||||
-rw-r--r-- | src/lread.c | 20 | ||||
-rw-r--r-- | src/macros.c | 4 | ||||
-rw-r--r-- | src/minibuf.c | 7 | ||||
-rw-r--r-- | src/nsmenu.m | 2 | ||||
-rw-r--r-- | src/nsterm.h | 4 | ||||
-rw-r--r-- | src/nsterm.m | 21 | ||||
-rw-r--r-- | src/process.c | 6 | ||||
-rw-r--r-- | src/region-cache.c | 13 | ||||
-rw-r--r-- | src/scroll.c | 41 | ||||
-rw-r--r-- | src/search.c | 16 | ||||
-rw-r--r-- | src/sysdep.c | 8 | ||||
-rw-r--r-- | src/term.c | 84 | ||||
-rw-r--r-- | src/termcap.c | 18 | ||||
-rw-r--r-- | src/termhooks.h | 6 | ||||
-rw-r--r-- | src/tparam.c | 29 | ||||
-rw-r--r-- | src/window.c | 2 | ||||
-rw-r--r-- | src/xdisp.c | 21 | ||||
-rw-r--r-- | src/xfaces.c | 14 | ||||
-rw-r--r-- | src/xfns.c | 41 | ||||
-rw-r--r-- | src/xgselect.c | 12 | ||||
-rw-r--r-- | src/xrdb.c | 21 | ||||
-rw-r--r-- | src/xselect.c | 307 | ||||
-rw-r--r-- | src/xsmfns.c | 3 | ||||
-rw-r--r-- | src/xterm.c | 48 |
59 files changed, 1430 insertions, 704 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 3eaa3d5eadd..a88e2e8e3cf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,358 @@ +2011-07-29 Paul Eggert <eggert@cs.ucla.edu> + + Integer and memory overflow issues. + + * bidi.c (bidi_shelve_header_size): New constant. + (bidi_cache_ensure_space, bidi_shelve_cache): Use it. + (bidi_cache_ensure_space): Avoid integer overflow when allocating. + + * buffer.c (overlays_at, overlays_in, record_overlay_string) + (overlay_strings): + Don't update size of array until after memory allocation succeeds, + because xmalloc/xrealloc may not return. + + * callproc.c (child_setup): Don't assume strlen fits in int. + + * ccl.c (Fccl_execute_on_string): Check for memory overflow. + Use ptrdiff_t rather than EMACS_INT where ptrdiff_t will do. + Redo buffer-overflow calculations to avoid integer overflow. + + * character.c (Fstring): Check for size-calculation overflow. + + * coding.c (produce_chars): Redo buffer-overflow calculations to avoid + unnecessary integer overflow. Check for size overflow. + (encode_coding_object): Don't update size until xmalloc succeeds. + + * composite.c (get_composition_id): Check for overflow in glyph + length calculations. + + Integer and memory overflow fixes for display code. + * dispextern.h (struct glyph_pool.nglyphs): Now ptrdiff_t, not int. + * dispnew.c (adjust_glyph_matrix, realloc_glyph_pool) + (scrolling_window): Check for overflow in size calculations. + (line_draw_cost, realloc_glyph_pool, add_row_entry): + Don't assume glyph table len fits in int. + (struct row_entry.bucket, row_entry_pool_size, row_entry_idx) + (row_table_size): Now ptrdiff_t, not int. + (scrolling_window): Avoid overflow in size calculations. + Don't update size until allocation succeeds. + * fns.c (concat): Check for overflow in size calculations. + (next_almost_prime): Verify NEXT_ALMOST_PRIME_LIMIT. + * lisp.h (RANGED_INTEGERP, TYPE_RANGED_INTEGERP): New macros. + (NEXT_ALMOST_PRIME_LIMIT): New constant. + + * doc.c (get_doc_string_buffer_size): Now ptrdiff_t, not int. + (get_doc_string): Check for size calculation overflow. + Don't update size until allocation succeeds. + (get_doc_string, Fsubstitute_command_keys): Use ptrdiff_t, not + EMACS_INT, where ptrdiff_t will do. + (Fsubstitute_command_keys): Check for string overflow. + + * editfns.c (set_time_zone_rule): Don't assume environment length + fits in int. + (message_length): Now ptrdiff_t, not int. + (Fmessage_box): Don't update size until allocation succeeds. + Don't assume message length fits in int. + (Fformat): Use ptrdiff_t, not EMACS_INT, where ptrdiff_t will do. + + * emacs.c (main, sort_args): Check for size-calculation overflow. + + * eval.c (init_eval_once, grow_specpdl): Don't update size until + alloc succeeds. + (call_debugger, grow_specpdl): Redo calculations to avoid overflow. + + * frame.c (set_menu_bar_lines, x_set_frame_parameters) + (x_set_scroll_bar_width, x_figure_window_size): + Check for integer overflow. + (x_set_alpha): Do not assume XINT fits in int. + + * frame.h (struct frame): Use int, not EMACS_INT, where int works. + This is for the members text_lines, text_cols, total_lines, total_cols, + where the system imposes an 'int' limit. + + * fringe.c (Fdefine_fringe_bitmap): + Don't update size until alloc works. + + * ftfont.c (ftfont_get_open_type_spec, setup_otf_gstring) + (ftfont_shape_by_flt): Check for integer overflow in size calculations. + + * gtkutil.c (get_utf8_string, xg_store_widget_in_map): + Check for size-calculation overflow. + (get_utf8_string): Use ptrdiff_t, not size_t, where either will + do, as we prefer signed integers. + (id_to_widget.max_size, id_to_widget.used) + (xg_store_widget_in_map, xg_remove_widget_from_map) + (xg_get_widget_from_map, xg_get_scroll_id_for_window) + (xg_remove_scroll_bar, xg_update_scrollbar_pos): + Use and return ptrdiff_t, not int. + (xg_gtk_scroll_destroy): Don't assume ptrdiff_t fits in int. + * gtkutil.h: Change prototypes to match the above. + + * image.c (RANGED_INTEGERP, TYPE_RANGED_INTEGERP): Remove; these + are duplicate now that they've been promoted to lisp.h. + (x_allocate_bitmap_record, x_alloc_image_color) + (make_image_cache, cache_image, xpm_load): + Don't update size until alloc is done. + (xpm_load, lookup_rgb_color, lookup_pixel_color, x_to_xcolors) + (x_detect_edges): + Check for size calculation overflow. + (ct_colors_allocated_max): New constant. + (x_to_xcolors, x_detect_edges): Reorder multiplicands to avoid + overflow. + + * keyboard.c (read_char, menu_bar_items, tool_bar_items) + (read_char_x_menu_prompt, read_char_minibuf_menu_width) + (read_char_minibuf_menu_prompt, follow_key, read_key_sequence): + Use ptrdiff_t, not int, to count maps. + (read_char_minibuf_menu_prompt): Check for overflow in size + calculations. Don't update size until allocation succeeds. Redo + calculations to avoid overflow. + * keyboard.h: Change prototypes to match the above. + + * keymap.c (cmm_size, current_minor_maps): Use ptrdiff_t, not int, + to count maps. + (current_minor_maps): Check for size calculation overflow. + * keymap.h: Change prototypes to match the above. + + * lread.c (read1, init_obarray): Don't update size until alloc done. + + * macros.c (Fstart_kbd_macro): Don't update size until alloc done. + (store_kbd_macro_char): Reorder multiplicands to avoid overflow. + + * minibuf.c (read_minibuf_noninteractive): Don't leak memory + on memory overflow. + + * nsterm.h (struct ns_color_table.size, struct ns_color_table.avail): + Now ptrdiff_t, not int. + * nsterm.m (ns_index_color): Use ptrdiff_t, not int, for table indexes. + (ns_draw_fringe_bitmap): Rewrite to avoid overflow. + + * process.c (Fnetwork_interface_list): Check for overflow + in size calculation. + + * region-cache.c (move_cache_gap): Check for size calculation overflow. + + * scroll.c (do_line_insertion_deletion_costs): Check for size calc + overflow. Don't bother calling xmalloc when xrealloc will do. + + * search.c (Freplace_match): Check for size calculation overflow. + (Fset_match_data): Don't assume list lengths fit in 'int'. + + * sysdep.c (system_process_attributes): Use ptrdiff_t, not int, + for command line length. Do not attempt to address one before the + beginning of an array, as that's not portable. + + * term.c (max_frame_lines): Remove; unused. + (encode_terminal_src_size, encode_terminal_dst_size): Now ptrdiff_t, + not int. + (encode_terminal_code, calculate_costs): Check for size + calculation overflow. + (encode_terminal_code): Use ptrdiff_t, not int, to record glyph + table lengths and related sizes. Don't update size until alloc + done. Redo calculations to avoid overflow. + (calculate_costs): Don't bother calling xmalloc when xrealloc will do. + + * termcap.c (tgetent): Use ptrdiff_t, not int, to record results of + subtracting pointers. + (gobble_line): Check for overflow more carefully. Don't update size + until alloc done. + + * tparam.c (tparam1): Use ptrdiff_t, not int, for sizes. + Don't update size until alloc done. + Redo size calculations to avoid overflow. + Check for size calculation overflow. + + * xdisp.c (store_mode_line_noprop_char, x_consider_frame_title): + Use ptrdiff_t, not int, for sizes. + (store_mode_line_noprop_char): Don't update size until alloc done. + + * xfaces.c (Finternal_make_lisp_face): Use ptrdiff_t, not int, for + sizes. Check for size calculation overflow. + (cache_face): Do not overflow in size calculation. + + * xfns.c (x_encode_text, x_set_name_internal) + (Fx_change_window_property): Use ptrdiff_t, not int, to count + sizes, since they can exceed INT_MAX in size. Check for size + calculation overflow. + + * xgselect.c (xg_select): Check for size calculation overflow. + Don't update size until alloc done. + + * xrdb.c (magic_file_p): Plug memory leak on size overflow. + (get_environ_db): Don't assume path length fits in int, + as sprintf is limited to int lengths. + + * xselect.c (X_LONG_SIZE, X_USHRT_MAX, X_ULONG_MAX): New macros. + Use them to make the following changes clearer. + (MAX_SELECTION_QUANTUM): Make the other bounds on this value clearer. + This change doesn't affect the value now, but it may help remind + future maintainers not to raise the value too much later. + (SELECTION_QUANTUM): Remove, replacing with ... + (selection_quantum): ... new function, which avoids overflow. + All uses changed. + (struct selection_data.size): Now ptrdiff_t, not int, to avoid + assumption that selection length fits in 'int'. + (x_reply_selection_request, x_handle_selection_request) + (x_get_window_property, receive_incremental_selection) + (x_get_window_property_as_lisp_data, selection_data_to_lisp_data) + (lisp_data_to_selection_data, clean_local_selection_data): + Use ptrdiff_t, not int, to record length of selection. + (x_reply_selection_request, x_get_window_property) + (receive_incremental_selection, x_property_data_to_lisp): + Redo calculations to avoid overflow. + (x_reply_selection_request): When sending hint, ceiling it at + X_ULONG_MAX rather than relying on wraparound overflow to send + something. + (x_get_window_property, receive_incremental_selection) + (lisp_data_to_selection_data, x_property_data_to_lisp): + Check for size-calculation overflow. + (x_get_window_property, receive_incremental_selection) + (lisp_data_to_selection_data, Fx_register_dnd_atom): + Don't store size until memory allocation succeeds. + (x_get_window_property): Plug memory leak on memory exhaustion. + Don't double-block input; malloc is safe here. Don't assume 2**34 + - 4 fits in unsigned long. Add an xassert to check + XGetWindowProperty overflow. Be more careful about overflow + calculations, and distinguish size from memory overflow better. + (receive_incremental_selection): When tracing, don't assume + unsigned int is less than INT_MAX. + (x_selection_data_to_lisp_data): Remove unnecessary (and in theory + harmful) conversions of unsigned short to int. + (lisp_data_to_selection_data): Don't assume that integers + in the range -65535 through -1 fit in an X unsigned short. + Don't assume that ULONG_MAX == X_ULONG_MAX. Don't store into + result parameters unless successful. Rely on cons_to_unsigned + to report problems with elements; the old code wasn't right anyway. + (x_check_property_data): Check for int overflow; we cannot use + a wider type due to X limits. + (x_handle_dnd_message): Use unsigned int, to avoid int overflow. + + * xsmfns.c (smc_save_yourself_CB): Check for size calc overflow. + + * xterm.c (x_color_cells, handle_one_xevent, x_term_init): + Check for size calculation overflow. + (x_color_cells): Don't store size until memory allocation succeeds. + (handle_one_xevent): Use ptrdiff_t, not int, for byte counts. + (x_term_init): Don't assume length fits in int (sprintf is limited + to int size). + + Use ptrdiff_t for composition IDs. + * character.c (lisp_string_width): + * composite.c (composition_table_size, n_compositions) + (get_composition_id, composition_gstring_from_id): + * dispextern.h (struct glyph_string.cmp_id, struct composition_it.id): + * xdisp.c (BUILD_COMPOSITE_GLYPH_STRING): + * window.c (Frecenter): + Use ptrdiff_t, not int, for composition IDs. + * composite.c (get_composition_id): Check for integer overflow. + * composite.h: Adjust prototypes to match the above changes. + + Use ptrdiff_t for hash table indexes. + * category.c (hash_get_category_set): + * ccl.c (ccl_driver): + * charset.h (struct charset.hash_index, CHECK_CHARSET_GET_ID): + * coding.c (coding_system_charset_list, detect_coding_system): + * coding.h (struct coding_system.id): + * composite.c (get_composition_id, gstring_lookup_cache): + * fns.c (hash_lookup, hash_put, Fgethash, Fputhash): + * image.c (xpm_get_color_table_h): + * lisp.h (hash_lookup, hash_put): + * minibuf.c (Ftest_completion): + Use ptrdiff_t for hash table indexes, not int (which is too + narrow, on 64-bit hosts) or EMACS_INT (which is too wide, on + 32-bit --with-wide-int hosts). + + * charset.c (Fdefine_charset_internal): Check for integer overflow. + Add a FIXME comment about memory leaks. + (syms_of_charset): Don't assume xmalloc returns. + + Don't assume that stated character widths fit in int. + * character.c (Fchar_width, c_string_width, lisp_string_width): + * character.h (CHAR_WIDTH): + * indent.c (MULTIBYTE_BYTES_WIDTH): + Use sanitize_char_width to avoid undefined and/or bad behavior + with outlandish widths. + * character.h (sanitize_tab_width): Renamed from sanitize_width, + now that we have two such functions. All uses changed. + (sanitize_char_width): New inline function. + + Don't assume that tab-width fits in int. + * character.h (sanitize_width): New inline function. + (SANE_TAB_WIDTH): New macro. + (ASCII_CHAR_WIDTH): Use it. + * indent.c (sane_tab_width): Remove. All uses replaced by + SANE_TAB_WIDTH (current_buffer). + * xdisp.c (init_iterator): Use SANE_TAB_WIDTH. + + * fileio.c: Integer overflow issues with file modes. + (Fset_file_modes, auto_save_1): Don't assume EMACS_INT fits in int. + + * charset.c (read_hex): New arg OVERFLOW. All uses changed. + Remove unreachable code. + (read_hex, load_charset_map_from_file): Check for integer overflow. + + * xterm.c: don't go over XClientMessageEvent limit + (scroll_bar_windows_size): Now ptrdiff_t, as we prefer signed. + (x_send_scroll_bar_event): Likewise. Check that the size does not + exceed limits imposed by XClientMessageEvent, as well as the usual + ptrdiff_t and size_t limits. + + * keyboard.c: Overflow, signedness and related fixes. + (make_lispy_movement): Use same integer type in forward decl + that is used in the definition. + (read_key_sequence, keyremap_step): + Change bufsize argument back to int, undoing my 2011-03-30 change. + We prefer signed types, and int is wide enough here. + (parse_tool_bar_item): Don't assume tool_bar_max_label_size is less + than TYPE_MAXIMUM (EMACS_INT) / 2. Don't let the label size grow + larger than STRING_BYTES_BOUND. Use ptrdiff_t for Emacs string + length, not size_t. Use ptrdiff_t for index, not int. + (keyremap_step, read_key_sequence): Redo bufsize check to avoid + possibility of integer overflow. + + Overflow, signedness and related fixes for images. + + * dispextern.h (struct it.stack[0].u.image.image_id) + (struct_it.image_id, struct image.id, struct image_cache.size) + (struct image_cache.used, struct image_cache.ref_count): + * gtkutil.c (update_frame_tool_bar): + * image.c (x_reference_bitmap, Fimage_size, Fimage_mask_p) + (Fimage_metadata, free_image_cache, clear_image_cache, lookup_image) + (cache_image, mark_image_cache, x_kill_gs_process, Flookup_image): + * nsmenu.m (update_frame_tool_bar): + * xdisp.c (calc_pixel_width_or_height): + * xfns.c (image_cache_refcount): + Image IDs are now ptrdiff_t, not int, to avoid arbitrary limits + on typical 64-bit hosts. + + * image.c (RANGED_INTEGERP, TYPE_RANGED_INTEGERP): New macros. + (x_bitmap_pixmap, x_create_x_image_and_pixmap): + Omit unnecessary casts to int. + (parse_image_spec): Check that integers fall into 'int' range + when the callers expect that. + (image_ascent): Redo ascent calculation to avoid int overflow. + (clear_image_cache): Avoid overflow when sqrt (INT_MAX) < nimages. + (lookup_image): Remove unnecessary tests. + (xbm_image_p): Locals are now of int, not EMACS_INT, + since parse_image_check makes sure they fit into int. + (png_load, gif_load, svg_load_image): + Prefer int to unsigned where either will do. + (tiff_handler): New function, combining the cores of the + old tiff_error_handler and tiff_warning_handler. This + function is rewritten to use vsnprintf and thereby avoid + stack buffer overflows. It uses only the features of vsnprintf + that are common to both POSIX and native Microsoft. + (tiff_error_handler, tiff_warning_handler): Use it. + (tiff_load, gif_load, imagemagick_load_image): + Don't assume :index value fits in 'int'. + (gif_load): Omit unnecessary cast to double, and avoid double-rounding. + (imagemagick_load_image): Check that crop parameters fit into + the integer types that MagickCropImage accepts. Don't assume + Vimagemagick_render_type has a nonnegative value. Don't assume + size_t fits in 'long'. + (gs_load): Use printmax_t to print the widest integers possible. + Check for integer overflow when computing image height and width. + 2011-07-28 Andreas Schwab <schwab@linux-m68k.org> * print.c (print_object): Print empty symbol as ##. diff --git a/src/bidi.c b/src/bidi.c index 697ebb92856..a1e5721f350 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -306,6 +306,21 @@ static ptrdiff_t bidi_cache_last_idx; /* slot of last cache hit */ static ptrdiff_t bidi_cache_start = 0; /* start of cache for this "stack" level */ +/* 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, + and we need the same size of our stack. */ +static ptrdiff_t bidi_cache_start_stack[IT_STACK_SIZE]; +static int bidi_cache_sp; + +/* Size of header used by bidi_shelve_cache. */ +enum + { + bidi_shelve_header_size = + (sizeof (bidi_cache_idx) + sizeof (bidi_cache_start_stack) + + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start) + + sizeof (bidi_cache_last_idx)) + }; + /* Reset the cache state to the empty state. We only reset the part of the cache relevant to iteration of the current object. Previous objects, which are pushed on the display iterator's stack, are left @@ -471,7 +486,8 @@ bidi_cache_ensure_space (ptrdiff_t idx) max (BUF_BYTES_MAX, STRING_BYTES_BOUND); /* Also, it cannot be larger than what C can represent. */ - ptrdiff_t c_bound = min (PTRDIFF_MAX, SIZE_MAX) / elsz; + ptrdiff_t c_bound = + (min (PTRDIFF_MAX, SIZE_MAX) - bidi_shelve_header_size) / elsz; if (min (string_or_buffer_bound, c_bound) <= idx) memory_full (SIZE_MAX); @@ -568,11 +584,6 @@ bidi_peek_at_next_level (struct bidi_it *bidi_it) /*********************************************************************** Pushing and popping the bidi iterator state ***********************************************************************/ -/* 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, - and we need the same size of our stack. */ -static ptrdiff_t bidi_cache_start_stack[IT_STACK_SIZE]; -static int bidi_cache_sp; /* Push the bidi iterator state in preparation for reordering a different object, e.g. display string found at certain buffer @@ -629,11 +640,8 @@ bidi_shelve_cache (void) if (bidi_cache_idx == 0) return NULL; - databuf = xmalloc (sizeof (bidi_cache_idx) - + bidi_cache_idx * sizeof (struct bidi_it) - + sizeof (bidi_cache_start_stack) - + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start) - + sizeof (bidi_cache_last_idx)); + databuf = xmalloc (bidi_shelve_header_size + + bidi_cache_idx * sizeof (struct bidi_it)); memcpy (databuf, &bidi_cache_idx, sizeof (bidi_cache_idx)); memcpy (databuf + sizeof (bidi_cache_idx), bidi_cache, bidi_cache_idx * sizeof (struct bidi_it)); diff --git a/src/buffer.c b/src/buffer.c index 45d6fa36d04..cacc8a41339 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2572,9 +2572,9 @@ overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, memory_full (SIZE_MAX); /* Make it work with an initial len == 0. */ len = len * 2 + 4; - *len_ptr = len; vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object)); *vec_ptr = vec; + *len_ptr = len; } else inhibit_storing = 1; @@ -2615,9 +2615,9 @@ overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, memory_full (SIZE_MAX); /* Make it work with an initial len == 0. */ len = len * 2 + 4; - *len_ptr = len; vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object)); *vec_ptr = vec; + *len_ptr = len; } else inhibit_storing = 1; @@ -2712,9 +2712,9 @@ overlays_in (EMACS_INT beg, EMACS_INT end, int extend, memory_full (SIZE_MAX); /* Make it work with an initial len == 0. */ len = len * 2 + 4; - *len_ptr = len; vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object)); *vec_ptr = vec; + *len_ptr = len; } else inhibit_storing = 1; @@ -2760,9 +2760,9 @@ overlays_in (EMACS_INT beg, EMACS_INT end, int extend, memory_full (SIZE_MAX); /* Make it work with an initial len == 0. */ len = len * 2 + 4; - *len_ptr = len; vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object)); *vec_ptr = vec; + *len_ptr = len; } else inhibit_storing = 1; @@ -2978,15 +2978,12 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, if (ssl->used == ssl->size) { - if (min (PTRDIFF_MAX, SIZE_MAX) / (sizeof (struct sortstr) * 2) - < ssl->size) + ptrdiff_t ssl_size = 0 < ssl->size ? ssl->size * 2 : 5; + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct sortstr) < ssl_size) memory_full (SIZE_MAX); - else if (0 < ssl->size) - ssl->size *= 2; - else - ssl->size = 5; ssl->buf = ((struct sortstr *) - xrealloc (ssl->buf, ssl->size * sizeof (struct sortstr))); + xrealloc (ssl->buf, ssl_size * sizeof (struct sortstr))); + ssl->size = ssl_size; } ssl->buf[ssl->used].string = str; ssl->buf[ssl->used].string2 = str2; @@ -3111,9 +3108,9 @@ overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) if (total > overlay_str_len) { - overlay_str_len = total; overlay_str_buf = (unsigned char *)xrealloc (overlay_str_buf, total); + overlay_str_len = total; } p = overlay_str_buf; for (i = overlay_tails.used; --i >= 0;) diff --git a/src/callproc.c b/src/callproc.c index f148f6233d4..993d943e158 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -1147,9 +1147,11 @@ child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, L cleaned up in the usual way. */ { register char *temp; - register int i; + register ptrdiff_t i; i = SBYTES (current_dir); + if (min (PTRDIFF_MAX, SIZE_MAX) - 6 < i) + memory_full (SIZE_MAX); #ifdef MSDOS /* MSDOS must have all environment variables malloc'ed, because low-level libc functions that launch subsidiary processes rely diff --git a/src/category.c b/src/category.c index 08eadb04730..a822bb654b0 100644 --- a/src/category.c +++ b/src/category.c @@ -67,7 +67,7 @@ static Lisp_Object hash_get_category_set (Lisp_Object table, Lisp_Object category_set) { struct Lisp_Hash_Table *h; - EMACS_INT i; + ptrdiff_t i; EMACS_UINT hash; if (NILP (XCHAR_TABLE (table)->extras[1])) diff --git a/src/ccl.c b/src/ccl.c index 9cfcbfe8703..0a9b3d90708 100644 --- a/src/ccl.c +++ b/src/ccl.c @@ -1303,7 +1303,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size case CCL_LookupIntConstTbl: { - EMACS_INT eop; + ptrdiff_t eop; struct Lisp_Hash_Table *h; GET_CCL_RANGE (eop, ccl_prog, ic++, 0, (VECTORP (Vtranslation_hash_table_vector) @@ -1329,7 +1329,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size case CCL_LookupCharConstTbl: { - EMACS_INT eop; + ptrdiff_t eop; struct Lisp_Hash_Table *h; GET_CCL_RANGE (eop, ccl_prog, ic++, 0, (VECTORP (Vtranslation_hash_table_vector) @@ -2061,12 +2061,12 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY Lisp_Object val; struct ccl_program ccl; int i; - EMACS_INT outbufsize; + ptrdiff_t outbufsize; unsigned char *outbuf, *outp; - EMACS_INT str_chars, str_bytes; + ptrdiff_t str_chars, str_bytes; #define CCL_EXECUTE_BUF_SIZE 1024 int source[CCL_EXECUTE_BUF_SIZE], destination[CCL_EXECUTE_BUF_SIZE]; - EMACS_INT consumed_chars, consumed_bytes, produced_chars; + ptrdiff_t consumed_chars, consumed_bytes, produced_chars; if (setup_ccl_program (&ccl, ccl_prog) < 0) error ("Invalid CCL program"); @@ -2093,6 +2093,10 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY ccl.ic = i; } + if (((min (PTRDIFF_MAX, SIZE_MAX) - 256) + / (ccl.buf_magnification ? ccl.buf_magnification : 1)) + < str_bytes) + memory_full (SIZE_MAX); outbufsize = (ccl.buf_magnification ? str_bytes * ccl.buf_magnification + 256 : str_bytes + 256); @@ -2127,11 +2131,19 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY produced_chars += ccl.produced; if (NILP (unibyte_p)) { - if (outp - outbuf + MAX_MULTIBYTE_LENGTH * ccl.produced - > outbufsize) + ptrdiff_t offset = outp - outbuf; + if ((outbufsize - offset) / MAX_MULTIBYTE_LENGTH < ccl.produced) { - EMACS_INT offset = outp - outbuf; - outbufsize += MAX_MULTIBYTE_LENGTH * ccl.produced; + ptrdiff_t produced; + if (((min (PTRDIFF_MAX, SIZE_MAX) - outbufsize) + / MAX_MULTIBYTE_LENGTH) + < ccl.produced) + { + xfree (outbuf); + memory_full (SIZE_MAX); + } + produced = ccl.produced; + outbufsize += MAX_MULTIBYTE_LENGTH * produced; outbuf = (unsigned char *) xrealloc (outbuf, outbufsize); outp = outbuf + offset; } @@ -2140,9 +2152,14 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY } else { - if (outp - outbuf + ccl.produced > outbufsize) + ptrdiff_t offset = outp - outbuf; + if (outbufsize - offset < ccl.produced) { - EMACS_INT offset = outp - outbuf; + if (min (PTRDIFF_MAX, SIZE_MAX) - outbufsize < ccl.produced) + { + xfree (outbuf); + memory_full (SIZE_MAX); + } outbufsize += ccl.produced; outbuf = (unsigned char *) xrealloc (outbuf, outbufsize); outp = outbuf + offset; diff --git a/src/character.c b/src/character.c index 8e9b3e3775e..50b5b252871 100644 --- a/src/character.c +++ b/src/character.c @@ -326,7 +326,7 @@ usage: (char-width CHAR) */) disp = dp ? DISP_CHAR_VECTOR (dp, c) : Qnil; if (VECTORP (disp)) - width = ASIZE (disp); + width = sanitize_char_width (ASIZE (disp)); else width = CHAR_WIDTH (c); @@ -358,7 +358,7 @@ c_string_width (const unsigned char *str, EMACS_INT len, int precision, { val = DISP_CHAR_VECTOR (dp, c); if (VECTORP (val)) - thiswidth = ASIZE (val); + thiswidth = sanitize_char_width (ASIZE (val)); else thiswidth = CHAR_WIDTH (c); } @@ -423,7 +423,7 @@ lisp_string_width (Lisp_Object string, EMACS_INT precision, { EMACS_INT chars, bytes, thiswidth; Lisp_Object val; - int cmp_id; + ptrdiff_t cmp_id; EMACS_INT ignore, end; if (find_composition (i, -1, &ignore, &end, &val, string) @@ -451,7 +451,7 @@ lisp_string_width (Lisp_Object string, EMACS_INT precision, { val = DISP_CHAR_VECTOR (dp, c); if (VECTORP (val)) - thiswidth = ASIZE (val); + thiswidth = sanitize_char_width (ASIZE (val)); else thiswidth = CHAR_WIDTH (c); } @@ -902,6 +902,8 @@ usage: (string &rest CHARACTERS) */) Lisp_Object str; USE_SAFE_ALLOCA; + if (min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH < n) + memory_full (SIZE_MAX); SAFE_ALLOCA (buf, unsigned char *, MAX_MULTIBYTE_LENGTH * n); p = buf; diff --git a/src/character.h b/src/character.h index 063b5147dc9..09bcf17ab96 100644 --- a/src/character.h +++ b/src/character.h @@ -556,6 +556,16 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ } while (0) +/* Return a non-outlandish value for the tab width. */ + +#define SANE_TAB_WIDTH(buf) \ + sanitize_tab_width (XFASTINT (BVAR (buf, tab_width))) +static inline int +sanitize_tab_width (EMACS_INT width) +{ + return 0 < width && width <= 1000 ? width : 8; +} + /* Return the width of ASCII character C. The width is measured by how many columns C will occupy on the screen when displayed in the current buffer. */ @@ -563,12 +573,20 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define ASCII_CHAR_WIDTH(c) \ (c < 0x20 \ ? (c == '\t' \ - ? XFASTINT (BVAR (current_buffer, tab_width)) \ + ? SANE_TAB_WIDTH (current_buffer) \ : (c == '\n' ? 0 : (NILP (BVAR (current_buffer, ctl_arrow)) ? 4 : 2))) \ : (c < 0x7f \ ? 1 \ : ((NILP (BVAR (current_buffer, ctl_arrow)) ? 4 : 2)))) +/* Return a non-outlandish value for a character width. */ + +static inline int +sanitize_char_width (EMACS_INT width) +{ + return 0 <= width && width <= 1000 ? width : 1000; +} + /* Return the width of character C. The width is measured by how many columns C will occupy on the screen when displayed in the current buffer. */ @@ -576,7 +594,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #define CHAR_WIDTH(c) \ (ASCII_CHAR_P (c) \ ? ASCII_CHAR_WIDTH (c) \ - : XINT (CHAR_TABLE_REF (Vchar_width_table, c))) + : sanitize_char_width (XINT (CHAR_TABLE_REF (Vchar_width_table, c)))) /* If C is a variation selector, return the index numnber of the variation selector (1..256). Otherwise, return 0. */ diff --git a/src/charset.c b/src/charset.c index 55234aa76aa..852aeb19bcb 100644 --- a/src/charset.c +++ b/src/charset.c @@ -419,7 +419,7 @@ load_charset_map (struct charset *charset, struct charset_map_entries *entries, paying attention to comment character '#'. */ static inline unsigned -read_hex (FILE *fp, int *eof) +read_hex (FILE *fp, int *eof, int *overflow) { int c; unsigned n; @@ -441,15 +441,16 @@ read_hex (FILE *fp, int *eof) *eof = 1; return 0; } - *eof = 0; n = 0; - if (c == 'x') - while ((c = getc (fp)) != EOF && isxdigit (c)) + while (isxdigit (c = getc (fp))) + { + if (UINT_MAX >> 4 < n) + *overflow = 1; n = ((n << 4) - | (c <= '9' ? c - '0' : c <= 'F' ? c - 'A' + 10 : c - 'a' + 10)); - else - while ((c = getc (fp)) != EOF && isdigit (c)) - n = (n * 10) + c - '0'; + | (c - ('0' <= c && c <= '9' ? '0' + : 'A' <= c && c <= 'F' ? 'A' - 10 + : 'a' - 10))); + } if (c != EOF) ungetc (c, fp); return n; @@ -479,7 +480,6 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co unsigned max_code = CHARSET_MAX_CODE (charset); int fd; FILE *fp; - int eof; Lisp_Object suffixes; struct charset_map_entries *head, *entries; int n_entries, count; @@ -504,22 +504,27 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co memset (entries, 0, sizeof (struct charset_map_entries)); n_entries = 0; - eof = 0; while (1) { - unsigned from, to; - int c; + unsigned from, to, c; int idx; + int eof = 0, overflow = 0; - from = read_hex (fp, &eof); + from = read_hex (fp, &eof, &overflow); if (eof) break; if (getc (fp) == '-') - to = read_hex (fp, &eof); + to = read_hex (fp, &eof, &overflow); else to = from; - c = (int) read_hex (fp, &eof); + if (eof) + break; + c = read_hex (fp, &eof, &overflow); + if (eof) + break; + if (overflow) + continue; if (from < min_code || to > max_code || from > to || c > MAX_CHAR) continue; @@ -1145,13 +1150,28 @@ usage: (define-charset-internal ...) */) hash_code); if (charset_table_used == charset_table_size) { - struct charset *new_table + struct charset *new_table; + /* Ensure that charset IDs fit into 'int' as well as into the + restriction imposed by fixnums, ptrdiff_t, and size_t. + Although the 'int' restriction could be removed, too much other + code would need altering; for example, the IDs are stuffed into + struct coding_system.charbuf[i] entries, which are 'int'. */ + int charset_table_size_max = + min (min (INT_MAX, MOST_POSITIVE_FIXNUM), + min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct charset)); + if (charset_table_size_max - 16 < charset_table_size) + memory_full (SIZE_MAX); + new_table = (struct charset *) xmalloc (sizeof (struct charset) * (charset_table_size + 16)); memcpy (new_table, charset_table, sizeof (struct charset) * charset_table_size); charset_table_size += 16; charset_table = new_table; + /* FIXME: Doesn't this leak memory? The old charset_table + becomes unreachable. If the memory leak is intentional, + a comment should be added to explain this. If not, the + old charset_table should be freed, using xfree. */ } id = charset_table_used++; new_definition_p = 1; @@ -2342,9 +2362,8 @@ syms_of_charset (void) Vcharset_hash_table = Fmake_hash_table (2, args); } + charset_table = (struct charset *) xmalloc (sizeof (struct charset) * 128); charset_table_size = 128; - charset_table = ((struct charset *) - xmalloc (sizeof (struct charset) * charset_table_size)); charset_table_used = 0; defsubr (&Scharsetp); diff --git a/src/charset.h b/src/charset.h index c2a52a38e7e..be02bc0feae 100644 --- a/src/charset.h +++ b/src/charset.h @@ -148,7 +148,7 @@ struct charset int id; /* Index to Vcharset_hash_table. */ - EMACS_INT hash_index; + ptrdiff_t hash_index; /* Dimension of the charset: 1, 2, 3, or 4. */ int dimension; @@ -341,7 +341,7 @@ extern int emacs_mule_charset[256]; number of the charset. Otherwise, signal an error. */ #define CHECK_CHARSET_GET_ID(x, id) \ do { \ - int idx; \ + ptrdiff_t idx; \ \ if (! SYMBOLP (x) || (idx = CHARSET_SYMBOL_HASH_INDEX (x)) < 0) \ wrong_type_argument (Qcharsetp, (x)); \ diff --git a/src/coding.c b/src/coding.c index 65c8a767c2b..5fd59d394d9 100644 --- a/src/coding.c +++ b/src/coding.c @@ -5838,7 +5838,7 @@ coding_charset_list (struct coding_system *coding) Lisp_Object coding_system_charset_list (Lisp_Object coding_system) { - int id; + ptrdiff_t id; Lisp_Object attrs, charset_list; CHECK_CODING_SYSTEM_GET_ID (coding_system, id); @@ -6683,8 +6683,12 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, break; } - if (dst + MAX_MULTIBYTE_LENGTH * to_nchars > dst_end) + if ((dst_end - dst) / MAX_MULTIBYTE_LENGTH < to_nchars) { + if (((min (PTRDIFF_MAX, SIZE_MAX) - (buf_end - buf)) + / MAX_MULTIBYTE_LENGTH) + < to_nchars) + memory_full (SIZE_MAX); dst = alloc_destination (coding, buf_end - buf + MAX_MULTIBYTE_LENGTH * to_nchars, @@ -7888,11 +7892,10 @@ encode_coding_object (struct coding_system *coding, } else if (EQ (dst_object, Qt)) { + ptrdiff_t dst_bytes = max (1, coding->src_chars); coding->dst_object = Qnil; - coding->dst_bytes = coding->src_chars; - if (coding->dst_bytes == 0) - coding->dst_bytes = 1; - coding->destination = (unsigned char *) xmalloc (coding->dst_bytes); + coding->destination = (unsigned char *) xmalloc (dst_bytes); + coding->dst_bytes = dst_bytes; coding->dst_multibyte = 0; } else @@ -8076,7 +8079,7 @@ detect_coding_system (const unsigned char *src, Lisp_Object attrs, eol_type; Lisp_Object val = Qnil; struct coding_system coding; - int id; + ptrdiff_t id; struct coding_detection_info detect_info; enum coding_category base_category; int null_byte_found = 0, eight_bit_found = 0; diff --git a/src/coding.h b/src/coding.h index 85e153dcc3a..fdf9b762e75 100644 --- a/src/coding.h +++ b/src/coding.h @@ -415,7 +415,7 @@ struct coding_system setup_coding_system. At the early stage of building time, this value is -1 in the array coding_categories to indicate that no coding-system of that category is yet defined. */ - int id; + ptrdiff_t id; /* Flag bits of the coding system. The meaning of each bit is common to all types of coding systems. */ diff --git a/src/composite.c b/src/composite.c index d402d5ad0c4..4ae1d6ebb68 100644 --- a/src/composite.c +++ b/src/composite.c @@ -142,10 +142,10 @@ Lisp_Object Qcomposition; struct composition **composition_table; /* The current size of `composition_table'. */ -static int composition_table_size; +static ptrdiff_t composition_table_size; /* Number of compositions currently made. */ -int n_compositions; +ptrdiff_t n_compositions; /* Hash table for compositions. The key is COMPONENTS-VEC of `composition' property. The value is the corresponding @@ -172,19 +172,29 @@ Lisp_Object composition_temp; If the composition is invalid, return -1. */ -int +ptrdiff_t get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, Lisp_Object prop, Lisp_Object string) { Lisp_Object id, length, components, key, *key_contents; - int glyph_len; + ptrdiff_t glyph_len; struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table); - EMACS_INT hash_index; + ptrdiff_t hash_index; EMACS_UINT hash_code; + enum composition_method method; struct composition *cmp; EMACS_INT i; int ch; + /* Maximum length of a string of glyphs. XftGlyphExtents limits this + to INT_MAX, and Emacs may limit it further. */ + enum { + glyph_len_max = + min (INT_MAX, + (min (PTRDIFF_MAX, SIZE_MAX) + / max (MAX_MULTIBYTE_LENGTH, 2 * sizeof (short)))) + }; + /* PROP should be Form-A: ((LENGTH . COMPONENTS) . MODIFICATION-FUNC) or @@ -260,18 +270,22 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, /* Check if we have sufficient memory to store this information. */ if (composition_table_size == 0) { - composition_table_size = 256; composition_table - = (struct composition **) xmalloc (sizeof (composition_table[0]) - * composition_table_size); + = (struct composition **) xmalloc (sizeof (composition_table[0]) * 256); + composition_table_size = 256; } else if (composition_table_size <= n_compositions) { - composition_table_size += 256; + if ((min (MOST_POSITIVE_FIXNUM, + min (PTRDIFF_MAX, SIZE_MAX) / sizeof composition_table[0]) + - 256) + < composition_table_size) + memory_full (SIZE_MAX); composition_table = (struct composition **) xrealloc (composition_table, sizeof (composition_table[0]) - * composition_table_size); + * (composition_table_size + 256)); + composition_table_size += 256; } key_contents = XVECTOR (key)->contents; @@ -316,18 +330,24 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, /* Register the composition in composition_hash_table. */ hash_index = hash_put (hash_table, key, id, hash_code); + method = (NILP (components) + ? COMPOSITION_RELATIVE + : ((INTEGERP (components) || STRINGP (components)) + ? COMPOSITION_WITH_ALTCHARS + : COMPOSITION_WITH_RULE_ALTCHARS)); + + glyph_len = (method == COMPOSITION_WITH_RULE_ALTCHARS + ? (ASIZE (key) + 1) / 2 + : ASIZE (key)); + + if (glyph_len_max < glyph_len) + memory_full (SIZE_MAX); + /* Register the composition in composition_table. */ cmp = (struct composition *) xmalloc (sizeof (struct composition)); - cmp->method = (NILP (components) - ? COMPOSITION_RELATIVE - : ((INTEGERP (components) || STRINGP (components)) - ? COMPOSITION_WITH_ALTCHARS - : COMPOSITION_WITH_RULE_ALTCHARS)); + cmp->method = method; cmp->hash_index = hash_index; - glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS - ? (ASIZE (key) + 1) / 2 - : ASIZE (key)); cmp->glyph_len = glyph_len; cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2); cmp->font = NULL; @@ -656,7 +676,7 @@ static Lisp_Object gstring_lookup_cache (Lisp_Object header) { struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); - EMACS_INT i = hash_lookup (h, header, NULL); + ptrdiff_t i = hash_lookup (h, header, NULL); return (i >= 0 ? HASH_VALUE (h, i) : Qnil); } @@ -691,7 +711,7 @@ composition_gstring_put_cache (Lisp_Object gstring, EMACS_INT len) } Lisp_Object -composition_gstring_from_id (int id) +composition_gstring_from_id (ptrdiff_t id) { struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); diff --git a/src/composite.h b/src/composite.h index 8cedfdbe352..c30c6832796 100644 --- a/src/composite.h +++ b/src/composite.h @@ -193,7 +193,7 @@ struct composition { void *font; /* Pointer to an array of x-offset and y-offset (by pixels) of - glyphs. This points to a sufficient memory space (sizeof (int) * + glyphs. This points to a sufficient memory space (sizeof (short) * glyph_len * 2) that is allocated when the composition is registered in composition_table. X-offset and Y-offset of Nth glyph are (2N)th and (2N+1)th elements respectively. */ @@ -204,7 +204,7 @@ struct composition { COMPOSITION-ID. */ extern struct composition **composition_table; /* Number of the currently registered compositions. */ -extern int n_compositions; +extern ptrdiff_t n_compositions; /* Mask bits for CHECK_MASK arg to update_compositions. For a change in the region FROM and TO, check compositions ... */ @@ -216,8 +216,8 @@ extern int n_compositions; extern Lisp_Object Qcomposition; extern Lisp_Object composition_hash_table; -extern int get_composition_id (EMACS_INT, EMACS_INT, EMACS_INT, - Lisp_Object, Lisp_Object); +extern ptrdiff_t get_composition_id (EMACS_INT, EMACS_INT, EMACS_INT, + Lisp_Object, Lisp_Object); extern int find_composition (EMACS_INT, EMACS_INT, EMACS_INT *, EMACS_INT *, Lisp_Object *, Lisp_Object); extern void update_compositions (EMACS_INT, EMACS_INT, int); @@ -299,7 +299,7 @@ struct face; struct font_metrics; extern Lisp_Object composition_gstring_put_cache (Lisp_Object, EMACS_INT); -extern Lisp_Object composition_gstring_from_id (int); +extern Lisp_Object composition_gstring_from_id (ptrdiff_t); extern int composition_gstring_p (Lisp_Object); extern int composition_gstring_width (Lisp_Object, EMACS_INT, EMACS_INT, struct font_metrics *); diff --git a/src/dispextern.h b/src/dispextern.h index dc44c698164..70f426f95a6 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -575,7 +575,7 @@ struct glyph_pool struct glyph *glyphs; /* Allocated size of `glyphs'. */ - int nglyphs; + ptrdiff_t nglyphs; /* Number of rows and columns in a matrix. */ int nrows, ncolumns; @@ -1240,7 +1240,7 @@ struct glyph_string struct composition *cmp; /* If not negative, this string describes a compos. */ - int cmp_id; + ptrdiff_t cmp_id; /* Start and end glyph indices in a glyph-string. */ int cmp_from, cmp_to; @@ -2056,7 +2056,7 @@ struct composition_it EMACS_INT stop_pos; /* ID number of the composition or glyph-string. If negative, we are not iterating over a composition now. */ - int id; + ptrdiff_t id; /* If non-negative, character that triggers the automatic composition at `stop_pos', and this is an automatic composition. If negative, this is a static composition. This is set to -2 @@ -2246,7 +2246,7 @@ struct it struct { Lisp_Object object; struct it_slice slice; - int image_id; + ptrdiff_t image_id; } image; /* method == GET_FROM_COMPOSITION */ struct { @@ -2376,7 +2376,7 @@ struct it enum glyphless_display_method glyphless_method; /* If what == IT_IMAGE, the id of the image to display. */ - int image_id; + ptrdiff_t image_id; /* Values from `slice' property. */ struct it_slice slice; @@ -2826,7 +2826,7 @@ struct image EMACS_UINT hash; /* Image id of this image. */ - int id; + ptrdiff_t id; /* Hash collision chain. */ struct image *next, *prev; @@ -2845,13 +2845,13 @@ struct image_cache struct image **images; /* Allocated size of `images'. */ - unsigned size; + ptrdiff_t size; /* Number of images in the cache. */ - unsigned used; + ptrdiff_t used; /* Reference count (number of frames sharing this cache). */ - int refcount; + ptrdiff_t refcount; }; @@ -3117,7 +3117,7 @@ void w32_reset_fringes (void); extern int x_bitmap_height (struct frame *, ptrdiff_t); extern int x_bitmap_width (struct frame *, ptrdiff_t); extern int x_bitmap_pixmap (struct frame *, ptrdiff_t); -extern void x_reference_bitmap (struct frame *, int); +extern void x_reference_bitmap (struct frame *, ptrdiff_t); extern ptrdiff_t x_create_bitmap_from_data (struct frame *, char *, unsigned int, unsigned int); extern ptrdiff_t x_create_bitmap_from_file (struct frame *, Lisp_Object); @@ -3138,7 +3138,7 @@ void clear_image_caches (Lisp_Object); void mark_image_cache (struct image_cache *); int valid_image_p (Lisp_Object); void prepare_image_for_display (struct frame *, struct image *); -int lookup_image (struct frame *, Lisp_Object); +ptrdiff_t lookup_image (struct frame *, Lisp_Object); unsigned long image_background (struct image *, struct frame *, XImagePtr_or_DC ximg); 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 /* Enlarge MATRIX->rows if necessary. New rows are cleared. */ if (matrix->rows_allocated < dim.height) { - ptrdiff_t size = dim.height * sizeof (struct glyph_row); + ptrdiff_t size; + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph_row) < dim.height) + memory_full (SIZE_MAX); + size = dim.height * sizeof (struct glyph_row); new_rows = dim.height - matrix->rows_allocated; matrix->rows = (struct glyph_row *) xrealloc (matrix->rows, size); 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 struct glyph_row *row = matrix->rows; struct glyph_row *end = row + matrix->rows_allocated; + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph) < dim.width) + memory_full (SIZE_MAX); + while (row < end) { row->glyphs[LEFT_MARGIN_AREA] @@ -1217,7 +1223,7 @@ line_draw_cost (struct glyph_matrix *matrix, int vpos) struct glyph *end = beg + row->used[TEXT_AREA]; int len; Lisp_Object *glyph_table_base = GLYPH_TABLE_BASE; - int glyph_table_len = GLYPH_TABLE_LENGTH; + ptrdiff_t glyph_table_len = GLYPH_TABLE_LENGTH; /* Ignore trailing and leading spaces if we can. */ if (!FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */ @@ -1391,31 +1397,26 @@ free_glyph_pool (struct glyph_pool *pool) static int realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim) { - int needed; + ptrdiff_t needed; int changed_p; changed_p = (pool->glyphs == 0 || matrix_dim.height != pool->nrows || matrix_dim.width != pool->ncolumns); + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph) / matrix_dim.width + < matrix_dim.height) + memory_full (SIZE_MAX); + /* Enlarge the glyph pool. */ - needed = matrix_dim.width * matrix_dim.height; + needed = matrix_dim.width; + needed *= matrix_dim.height; if (needed > pool->nglyphs) { ptrdiff_t size = needed * sizeof (struct glyph); - - if (pool->glyphs) - { - pool->glyphs = (struct glyph *) xrealloc (pool->glyphs, size); - memset (pool->glyphs + pool->nglyphs, 0, - size - pool->nglyphs * sizeof (struct glyph)); - } - else - { - pool->glyphs = (struct glyph *) xmalloc (size); - memset (pool->glyphs, 0, size); - } - + pool->glyphs = (struct glyph *) xrealloc (pool->glyphs, size); + memset (pool->glyphs + pool->nglyphs, 0, + size - pool->nglyphs * sizeof (struct glyph)); pool->nglyphs = needed; } @@ -4166,7 +4167,7 @@ struct row_entry int new_line_number; /* Bucket index of this row_entry in the hash table row_table. */ - int bucket; + ptrdiff_t bucket; /* The row described by this entry. */ struct glyph_row *row; @@ -4180,18 +4181,18 @@ struct row_entry that we need a larger one. */ static struct row_entry *row_entry_pool; -static int row_entry_pool_size; +static ptrdiff_t row_entry_pool_size; /* Index of next free entry in row_entry_pool. */ -static int row_entry_idx; +static ptrdiff_t row_entry_idx; /* The hash table used during scrolling, and the table's size. This table is used to quickly identify equal rows in the desired and current matrix. */ static struct row_entry **row_table; -static int row_table_size; +static ptrdiff_t row_table_size; /* Vectors of pointers to row_entry structures belonging to the current and desired matrix, and the size of the vectors. */ @@ -4214,7 +4215,7 @@ static inline struct row_entry * add_row_entry (struct glyph_row *row) { struct row_entry *entry; - int i = row->hash % row_table_size; + ptrdiff_t i = row->hash % row_table_size; entry = row_table[i]; while (entry && !row_equal_p (entry->row, row, 1)) @@ -4267,9 +4268,10 @@ scrolling_window (struct window *w, int header_line_p) struct glyph_matrix *desired_matrix = w->desired_matrix; struct glyph_matrix *current_matrix = w->current_matrix; int yb = window_text_bottom_y (w); - int i, j, first_old, first_new, last_old, last_new; - int nruns, n, run_idx; - ptrdiff_t nbytes; + ptrdiff_t i; + int j, first_old, first_new, last_old, last_new; + int nruns, run_idx; + ptrdiff_t n, nbytes; struct row_entry *entry; struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); @@ -4354,45 +4356,77 @@ scrolling_window (struct window *w, int header_line_p) if (last_new == first_new) return 0; + /* Check for integer overflow in xrealloc size calculation. + + If next_almost_prime checks (N) for divisibility by 2..10, then + it can return at most N + 10, e.g., next_almost_prime (1) == 11. + So, set next_almost_prime_increment_max to 10. + + It's just a coincidence that next_almost_prime_increment_max == + NEXT_ALMOST_PRIME_LIMIT - 1. If NEXT_ALMOST_PRIME_LIMIT were + 13, then next_almost_prime_increment_max would be 14, e.g., + because next_almost_prime (113) would be 127. */ + { + verify (NEXT_ALMOST_PRIME_LIMIT == 11); + enum { next_almost_prime_increment_max = 10 }; + ptrdiff_t alloc_max = min (PTRDIFF_MAX, SIZE_MAX); + ptrdiff_t row_table_max = + ((alloc_max - next_almost_prime_increment_max) + / (3 * sizeof *row_table)); + ptrdiff_t row_entry_pool_max = alloc_max / sizeof *row_entry_pool; + int n_max = min (INT_MAX, min (row_table_max, row_entry_pool_max)); + ptrdiff_t old_lines_max = alloc_max / sizeof *old_lines; + int current_nrows_max = min (n_max - desired_matrix->nrows, old_lines_max); + int desired_nrows_max = + min (INT_MAX, + alloc_max / max (sizeof *new_lines, + max (sizeof *runs, sizeof *run_pool))); + if (current_nrows_max < current_matrix->nrows + || desired_nrows_max < desired_matrix->nrows) + memory_full (SIZE_MAX); + } + /* Reallocate vectors, tables etc. if necessary. */ if (current_matrix->nrows > old_lines_size) { - old_lines_size = current_matrix->nrows; - nbytes = old_lines_size * sizeof *old_lines; + nbytes = current_matrix->nrows * sizeof *old_lines; old_lines = (struct row_entry **) xrealloc (old_lines, nbytes); + old_lines_size = current_matrix->nrows; } if (desired_matrix->nrows > new_lines_size) { - new_lines_size = desired_matrix->nrows; - nbytes = new_lines_size * sizeof *new_lines; + nbytes = desired_matrix->nrows * sizeof *new_lines; new_lines = (struct row_entry **) xrealloc (new_lines, nbytes); + new_lines_size = desired_matrix->nrows; } - n = desired_matrix->nrows + current_matrix->nrows; - if (3 * n > row_table_size) + n = desired_matrix->nrows; + n += current_matrix->nrows; + if (row_table_size / 3 < n) { - row_table_size = next_almost_prime (3 * n); - nbytes = row_table_size * sizeof *row_table; + ptrdiff_t size = next_almost_prime (3 * n); + nbytes = size * sizeof *row_table; row_table = (struct row_entry **) xrealloc (row_table, nbytes); + row_table_size = size; memset (row_table, 0, nbytes); } if (n > row_entry_pool_size) { - row_entry_pool_size = n; - nbytes = row_entry_pool_size * sizeof *row_entry_pool; + nbytes = n * sizeof *row_entry_pool; row_entry_pool = (struct row_entry *) xrealloc (row_entry_pool, nbytes); + row_entry_pool_size = n; } if (desired_matrix->nrows > runs_size) { - runs_size = desired_matrix->nrows; - nbytes = runs_size * sizeof *runs; + nbytes = desired_matrix->nrows * sizeof *runs; runs = (struct run **) xrealloc (runs, nbytes); - nbytes = runs_size * sizeof *run_pool; + nbytes = desired_matrix->nrows * sizeof *run_pool; run_pool = (struct run *) xrealloc (run_pool, nbytes); + runs_size = desired_matrix->nrows; } nruns = run_idx = 0; diff --git a/src/doc.c b/src/doc.c index 69646f5af51..bd1831dde0e 100644 --- a/src/doc.c +++ b/src/doc.c @@ -39,7 +39,7 @@ Lisp_Object Qfunction_documentation; extern Lisp_Object Qclosure; /* Buffer used for reading from documentation file. */ static char *get_doc_string_buffer; -static int get_doc_string_buffer_size; +static ptrdiff_t get_doc_string_buffer_size; static unsigned char *read_bytecode_pointer; static Lisp_Object Fdocumentation_property (Lisp_Object, Lisp_Object, @@ -166,18 +166,23 @@ get_doc_string (Lisp_Object filepos, int unibyte, int definition) p = get_doc_string_buffer; while (1) { - EMACS_INT space_left = (get_doc_string_buffer_size + ptrdiff_t space_left = (get_doc_string_buffer_size - (p - get_doc_string_buffer)); int nread; /* Allocate or grow the buffer if we need to. */ if (space_left == 0) { - EMACS_INT in_buffer = p - get_doc_string_buffer; - get_doc_string_buffer_size += 16 * 1024; + ptrdiff_t in_buffer = p - get_doc_string_buffer; + enum { incr = 16 * 1024 }; + ptrdiff_t size; + if (min (PTRDIFF_MAX, SIZE_MAX) - 1 - incr + < get_doc_string_buffer_size) + memory_full (SIZE_MAX); + size = get_doc_string_buffer_size + incr; get_doc_string_buffer - = (char *) xrealloc (get_doc_string_buffer, - get_doc_string_buffer_size + 1); + = (char *) xrealloc (get_doc_string_buffer, size + 1); + get_doc_string_buffer_size = size; p = get_doc_string_buffer + in_buffer; space_left = (get_doc_string_buffer_size - (p - get_doc_string_buffer)); @@ -713,16 +718,16 @@ a new string, without any text properties, is returned. */) int changed = 0; register unsigned char *strp; register char *bufp; - EMACS_INT idx; - EMACS_INT bsize; + ptrdiff_t idx; + ptrdiff_t bsize; Lisp_Object tem; Lisp_Object keymap; unsigned char *start; - EMACS_INT length, length_byte; + ptrdiff_t length, length_byte; Lisp_Object name; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; int multibyte; - EMACS_INT nchars; + ptrdiff_t nchars; if (NILP (string)) return Qnil; @@ -774,7 +779,7 @@ a new string, without any text properties, is returned. */) } else if (strp[0] == '\\' && strp[1] == '[') { - EMACS_INT start_idx; + ptrdiff_t start_idx; int follow_remap = 1; changed = 1; @@ -813,7 +818,9 @@ a new string, without any text properties, is returned. */) if (NILP (tem)) /* but not on any keys */ { - EMACS_INT offset = bufp - buf; + ptrdiff_t offset = bufp - buf; + if (STRING_BYTES_BOUND - 4 < bsize) + string_overflow (); buf = (char *) xrealloc (buf, bsize += 4); bufp = buf + offset; memcpy (bufp, "M-x ", 4); @@ -836,7 +843,7 @@ a new string, without any text properties, is returned. */) else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<')) { struct buffer *oldbuf; - EMACS_INT start_idx; + ptrdiff_t start_idx; /* This is for computing the SHADOWS arg for describe_map_tree. */ Lisp_Object active_maps = Fcurrent_active_maps (Qnil, Qnil); Lisp_Object earlier_maps; @@ -907,7 +914,9 @@ a new string, without any text properties, is returned. */) length_byte = SBYTES (tem); subst: { - EMACS_INT offset = bufp - buf; + ptrdiff_t offset = bufp - buf; + if (STRING_BYTES_BOUND - length_byte < bsize) + string_overflow (); buf = (char *) xrealloc (buf, bsize += length_byte); bufp = buf + offset; memcpy (bufp, start, length_byte); diff --git a/src/editfns.c b/src/editfns.c index 577263c5aea..4e1b46b82c3 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2100,7 +2100,7 @@ static char set_time_zone_rule_tz2[] = "TZ=GMT+1"; void set_time_zone_rule (const char *tzstring) { - int envptrs; + ptrdiff_t envptrs; char **from, **to, **newenv; /* Make the ENVIRON vector longer with room for TZSTRING. */ @@ -3350,7 +3350,7 @@ usage: (save-restriction &rest BODY) */) static char *message_text; /* Allocated length of that buffer. */ -static int message_length; +static ptrdiff_t message_length; DEFUN ("message", Fmessage, Smessage, 1, MANY, 0, doc: /* Display a message at the bottom of the screen. @@ -3432,8 +3432,8 @@ usage: (message-box FORMAT-STRING &rest ARGS) */) } if (SBYTES (val) > message_length) { + message_text = (char *) xrealloc (message_text, SBYTES (val)); message_length = SBYTES (val); - message_text = (char *)xrealloc (message_text, message_length); } memcpy (message_text, SDATA (val), SBYTES (val)); message2 (message_text, SBYTES (val), @@ -4158,7 +4158,7 @@ usage: (format STRING &rest OBJECTS) */) character. CONVBYTES says how much room is needed. Allocate enough room (and then some) and do it again. */ { - EMACS_INT used = p - buf; + ptrdiff_t used = p - buf; if (max_bufsize - used < convbytes) string_overflow (); diff --git a/src/emacs.c b/src/emacs.c index 39870ec0079..4de567a5588 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1360,9 +1360,12 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem This requires inserting a new element into argv. */ if (displayname != 0 && skip_args - count_before == 1) { - char **new = (char **) xmalloc (sizeof (char *) * (argc + 2)); + char **new; int j; + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (char *) - 2 < argc) + memory_full (SIZE_MAX); + new = (char **) xmalloc (sizeof *new * argc + sizeof *new * 2); for (j = 0; j < count_before + 1; j++) new[j] = argv[j]; new[count_before + 1] = (char *) "-d"; @@ -1838,13 +1841,19 @@ sort_args (int argc, char **argv) 0 for an option that takes no arguments, 1 for an option that takes one argument, etc. -1 for an ordinary non-option argument. */ - int *options = (int *) xmalloc (sizeof (int) * argc); - int *priority = (int *) xmalloc (sizeof (int) * argc); + int *options; + int *priority; int to = 1; int incoming_used = 1; int from; int i; + if (sizeof (char *) < sizeof (int) + && min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < argc) + memory_full (SIZE_MAX); + options = (int *) xmalloc (sizeof (int) * argc); + priority = (int *) xmalloc (sizeof (int) * argc); + /* Categorize all the options, and figure out which argv elts are option arguments. */ for (from = 1; from < argc; from++) diff --git a/src/eval.c b/src/eval.c index ef169e80e27..bcb77574fee 100644 --- a/src/eval.c +++ b/src/eval.c @@ -133,8 +133,9 @@ static Lisp_Object Ffetch_bytecode (Lisp_Object); void init_eval_once (void) { - specpdl_size = 50; - specpdl = (struct specbinding *) xmalloc (specpdl_size * sizeof (struct specbinding)); + enum { size = 50 }; + specpdl = (struct specbinding *) xmalloc (size * sizeof (struct specbinding)); + specpdl_size = size; specpdl_ptr = specpdl; /* Don't forget to update docs (lispref node "Local Variables"). */ max_specpdl_size = 1300; /* 1000 is not enough for CEDET's c-by.el. */ @@ -192,7 +193,7 @@ call_debugger (Lisp_Object arg) if (lisp_eval_depth + 40 > max_lisp_eval_depth) max_lisp_eval_depth = lisp_eval_depth + 40; - if (SPECPDL_INDEX () + 100 > max_specpdl_size) + if (max_specpdl_size - 100 < SPECPDL_INDEX ()) max_specpdl_size = SPECPDL_INDEX () + 100; #ifdef HAVE_WINDOW_SYSTEM @@ -3274,17 +3275,22 @@ static void grow_specpdl (void) { register int count = SPECPDL_INDEX (); - if (specpdl_size >= max_specpdl_size) + int max_size = + min (max_specpdl_size, + min (max (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct specbinding), + INT_MAX)); + int size; + if (max_size <= specpdl_size) { if (max_specpdl_size < 400) - max_specpdl_size = 400; - if (specpdl_size >= max_specpdl_size) + max_size = max_specpdl_size = 400; + if (max_size <= specpdl_size) signal_error ("Variable binding depth exceeds max-specpdl-size", Qnil); } - specpdl_size *= 2; - if (specpdl_size > max_specpdl_size) - specpdl_size = max_specpdl_size; - specpdl = (struct specbinding *) xrealloc (specpdl, specpdl_size * sizeof (struct specbinding)); + size = specpdl_size < max_size / 2 ? 2 * specpdl_size : max_size; + specpdl = ((struct specbinding *) + xrealloc (specpdl, size * sizeof (struct specbinding))); + specpdl_size = size; specpdl_ptr = specpdl + count; } diff --git a/src/fileio.c b/src/fileio.c index 61713689351..60ee35bb399 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2912,7 +2912,7 @@ symbolic notation, like the `chmod' command from GNU Coreutils. */) encoded_absname = ENCODE_FILE (absname); - if (chmod (SSDATA (encoded_absname), XINT (mode)) < 0) + if (chmod (SSDATA (encoded_absname), XINT (mode) & 07777) < 0) report_file_error ("Doing chmod", Fcons (absname, Qnil)); return Qnil; @@ -5114,11 +5114,11 @@ auto_save_1 (void) { if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0) /* But make sure we can overwrite it later! */ - auto_save_mode_bits = st.st_mode | 0600; + auto_save_mode_bits = (st.st_mode | 0600) & 0777; else if ((modes = Ffile_modes (BVAR (current_buffer, filename)), INTEGERP (modes))) /* Remote files don't cooperate with stat. */ - auto_save_mode_bits = XINT (modes) | 0600; + auto_save_mode_bits = (XINT (modes) | 0600) & 0777; } return diff --git a/src/fns.c b/src/fns.c index 9c9d19fe26a..e5538d6acbc 100644 --- a/src/fns.c +++ b/src/fns.c @@ -602,7 +602,12 @@ concat (ptrdiff_t nargs, Lisp_Object *args, prev = Qnil; if (STRINGP (val)) - SAFE_ALLOCA (textprops, struct textprop_rec *, sizeof (struct textprop_rec) * nargs); + { + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *textprops < nargs) + memory_full (SIZE_MAX); + SAFE_ALLOCA (textprops, struct textprop_rec *, + sizeof *textprops * nargs); + } for (argnum = 0; argnum < nargs; argnum++) { @@ -3395,11 +3400,13 @@ check_hash_table (Lisp_Object obj) /* Value is the next integer I >= N, N >= 0 which is "almost" a prime - number. */ + number. A number is "almost" a prime number if it is not divisible + by any integer in the range 2 .. (NEXT_ALMOST_PRIME_LIMIT - 1). */ EMACS_INT next_almost_prime (EMACS_INT n) { + verify (NEXT_ALMOST_PRIME_LIMIT == 11); for (n |= 1; ; n += 2) if (n % 3 != 0 && n % 5 != 0 && n % 7 != 0) return n; @@ -3787,11 +3794,11 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) the hash code of KEY. Value is the index of the entry in H matching KEY, or -1 if not found. */ -EMACS_INT +ptrdiff_t hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash) { EMACS_UINT hash_code; - EMACS_INT start_of_bucket; + ptrdiff_t start_of_bucket; Lisp_Object idx; hash_code = h->hashfn (h, key); @@ -3821,11 +3828,11 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash) HASH is a previously computed hash code of KEY. Value is the index of the entry in H matching KEY. */ -EMACS_INT +ptrdiff_t hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, EMACS_UINT hash) { - EMACS_INT start_of_bucket, i; + ptrdiff_t start_of_bucket, i; xassert ((hash & ~INTMASK) == 0); @@ -4482,7 +4489,7 @@ If KEY is not found, return DFLT which defaults to nil. */) (Lisp_Object key, Lisp_Object table, Lisp_Object dflt) { struct Lisp_Hash_Table *h = check_hash_table (table); - EMACS_INT i = hash_lookup (h, key, NULL); + ptrdiff_t i = hash_lookup (h, key, NULL); return i >= 0 ? HASH_VALUE (h, i) : dflt; } @@ -4494,7 +4501,7 @@ VALUE. In any case, return VALUE. */) (Lisp_Object key, Lisp_Object value, Lisp_Object table) { struct Lisp_Hash_Table *h = check_hash_table (table); - EMACS_INT i; + ptrdiff_t i; EMACS_UINT hash; i = hash_lookup (h, key, &hash); diff --git a/src/frame.c b/src/frame.c index 19ce78dfd9c..711109a70c6 100644 --- a/src/frame.c +++ b/src/frame.c @@ -160,7 +160,7 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) if (FRAME_MINIBUF_ONLY_P (f)) return; - if (INTEGERP (value)) + if (TYPE_RANGED_INTEGERP (int, value)) nlines = XINT (value); else nlines = 0; @@ -2992,7 +2992,7 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist) f->size_hint_flags &= ~ (XNegative | YNegative); if (EQ (left, Qminus)) f->size_hint_flags |= XNegative; - else if (INTEGERP (left)) + else if (TYPE_RANGED_INTEGERP (int, left)) { leftpos = XINT (left); if (leftpos < 0) @@ -3000,21 +3000,21 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist) } else if (CONSP (left) && EQ (XCAR (left), Qminus) && CONSP (XCDR (left)) - && INTEGERP (XCAR (XCDR (left)))) + && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX)) { leftpos = - XINT (XCAR (XCDR (left))); f->size_hint_flags |= XNegative; } else if (CONSP (left) && EQ (XCAR (left), Qplus) && CONSP (XCDR (left)) - && INTEGERP (XCAR (XCDR (left)))) + && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left)))) { leftpos = XINT (XCAR (XCDR (left))); } if (EQ (top, Qminus)) f->size_hint_flags |= YNegative; - else if (INTEGERP (top)) + else if (TYPE_RANGED_INTEGERP (int, top)) { toppos = XINT (top); if (toppos < 0) @@ -3022,14 +3022,14 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist) } else if (CONSP (top) && EQ (XCAR (top), Qminus) && CONSP (XCDR (top)) - && INTEGERP (XCAR (XCDR (top)))) + && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX)) { toppos = - XINT (XCAR (XCDR (top))); f->size_hint_flags |= YNegative; } else if (CONSP (top) && EQ (XCAR (top), Qplus) && CONSP (XCDR (top)) - && INTEGERP (XCAR (XCDR (top)))) + && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top)))) { toppos = XINT (XCAR (XCDR (top))); } @@ -3481,7 +3481,7 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); do_pending_window_change (0); } - else if (INTEGERP (arg) && XINT (arg) > 0 + else if (RANGED_INTEGERP (1, arg, INT_MAX) && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f)) { if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM) @@ -3520,7 +3520,7 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { double alpha = 1.0; double newval[2]; - int i, ialpha; + int i; Lisp_Object item; for (i = 0; i < 2; i++) @@ -3544,7 +3544,7 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval) } else if (INTEGERP (item)) { - ialpha = XINT (item); + EMACS_INT ialpha = XINT (item); if (ialpha < 0 || 100 < ialpha) args_out_of_range (make_number (0), make_number (100)); else @@ -4031,11 +4031,15 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p) if (!EQ (tem0, Qunbound)) { CHECK_NUMBER (tem0); + if (! (0 <= XINT (tem0) && XINT (tem0) <= INT_MAX)) + xsignal1 (Qargs_out_of_range, tem0); FRAME_LINES (f) = XINT (tem0); } if (!EQ (tem1, Qunbound)) { CHECK_NUMBER (tem1); + if (! (0 <= XINT (tem1) && XINT (tem1) <= INT_MAX)) + xsignal1 (Qargs_out_of_range, tem1); SET_FRAME_COLS (f, XINT (tem1)); } if (!NILP (tem2) && !EQ (tem2, Qunbound)) @@ -4066,12 +4070,10 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p) ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF); - if (INTEGERP (Vtool_bar_button_margin) - && XINT (Vtool_bar_button_margin) > 0) + if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX)) margin = XFASTINT (Vtool_bar_button_margin); else if (CONSP (Vtool_bar_button_margin) - && INTEGERP (XCDR (Vtool_bar_button_margin)) - && XINT (XCDR (Vtool_bar_button_margin)) > 0) + && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX)) margin = XFASTINT (XCDR (Vtool_bar_button_margin)); else margin = 0; @@ -4097,14 +4099,14 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p) } else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus) && CONSP (XCDR (tem0)) - && INTEGERP (XCAR (XCDR (tem0)))) + && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem0)), INT_MAX)) { f->top_pos = - XINT (XCAR (XCDR (tem0))); window_prompting |= YNegative; } else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus) && CONSP (XCDR (tem0)) - && INTEGERP (XCAR (XCDR (tem0)))) + && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem0)))) { f->top_pos = XINT (XCAR (XCDR (tem0))); } @@ -4125,14 +4127,14 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p) } else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus) && CONSP (XCDR (tem1)) - && INTEGERP (XCAR (XCDR (tem1)))) + && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem1)), INT_MAX)) { f->left_pos = - XINT (XCAR (XCDR (tem1))); window_prompting |= XNegative; } else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus) && CONSP (XCDR (tem1)) - && INTEGERP (XCAR (XCDR (tem1)))) + && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem1)))) { f->left_pos = XINT (XCAR (XCDR (tem1))); } diff --git a/src/frame.h b/src/frame.h index 8dccfb8540a..3775403810f 100644 --- a/src/frame.h +++ b/src/frame.h @@ -258,11 +258,11 @@ struct frame /* Size of this frame, excluding fringes, scroll bars etc., in units of canonical characters. */ - EMACS_INT text_lines, text_cols; + int text_lines, text_cols; /* Total size of this frame (i.e. its native window), in units of canonical characters. */ - EMACS_INT total_lines, total_cols; + int total_lines, total_cols; /* New text height and width for pending size change. 0 if no change pending. */ diff --git a/src/fringe.c b/src/fringe.c index a4dc9433aff..5878c541247 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -1610,22 +1610,25 @@ If BITMAP already exists, the existing definition is replaced. */) if (n == max_fringe_bitmaps) { - if ((max_fringe_bitmaps + 20) > MAX_FRINGE_BITMAPS) + int bitmaps = max_fringe_bitmaps + 20; + if (MAX_FRINGE_BITMAPS < bitmaps) error ("No free fringe bitmap slots"); i = max_fringe_bitmaps; - max_fringe_bitmaps += 20; fringe_bitmaps = ((struct fringe_bitmap **) - xrealloc (fringe_bitmaps, max_fringe_bitmaps * sizeof (struct fringe_bitmap *))); + xrealloc (fringe_bitmaps, bitmaps * sizeof *fringe_bitmaps)); fringe_faces - = (Lisp_Object *) xrealloc (fringe_faces, max_fringe_bitmaps * sizeof (Lisp_Object)); + = (Lisp_Object *) xrealloc (fringe_faces, + bitmaps * sizeof *fringe_faces); - for (; i < max_fringe_bitmaps; i++) + for (i = max_fringe_bitmaps; i < bitmaps; i++) { fringe_bitmaps[i] = NULL; fringe_faces[i] = Qnil; } + + max_fringe_bitmaps = bitmaps; } } diff --git a/src/ftfont.c b/src/ftfont.c index 4e313a89021..551006eef94 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -682,7 +682,10 @@ ftfont_get_open_type_spec (Lisp_Object otf_spec) if (NILP (val)) continue; len = Flength (val); - spec->features[i] = malloc (sizeof (int) * XINT (len)); + spec->features[i] = + (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len) + ? 0 + : malloc (sizeof (int) * XINT (len))); if (! spec->features[i]) { if (i > 0 && spec->features[0]) @@ -1761,6 +1764,9 @@ static OTF_GlyphString otf_gstring; static void setup_otf_gstring (int size) { + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (OTF_Glyph) < size) + memory_full (SIZE_MAX); + if (otf_gstring.size == 0) { otf_gstring.glyphs = (OTF_Glyph *) xmalloc (sizeof (OTF_Glyph) * size); @@ -2390,6 +2396,8 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, struct MFLTFontFT flt_font_ft; MFLT *flt = NULL; int with_variation_selector = 0; + int allocated_max = min (INT_MAX, + min (PTRDIFF_MAX, SIZE_MAX) / sizeof (MFLTGlyph)); if (! m17n_flt_initialized) { @@ -2445,6 +2453,9 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, } } + if (allocated_max / 2 < len) + memory_full (SIZE_MAX); + if (gstring.allocated == 0) { gstring.allocated = len * 2; @@ -2504,6 +2515,8 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt); if (result != -2) break; + if (allocated_max / 2 < gstring.allocated) + memory_full (SIZE_MAX); gstring.allocated += gstring.allocated; gstring.glyphs = xrealloc (gstring.glyphs, sizeof (MFLTGlyph) * gstring.allocated); diff --git a/src/gtkutil.c b/src/gtkutil.c index 8826b08851a..f56e888e685 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -487,7 +487,8 @@ get_utf8_string (const char *str) if (!utf8_str) { /* Probably some control characters in str. Escape them. */ - size_t nr_bad = 0; + ptrdiff_t len; + ptrdiff_t nr_bad = 0; gsize bytes_read; gsize bytes_written; unsigned char *p = (unsigned char *)str; @@ -511,7 +512,10 @@ get_utf8_string (const char *str) } if (cp) g_free (cp); - up = utf8_str = xmalloc (strlen (str) + nr_bad * 4 + 1); + len = strlen (str); + if ((min (PTRDIFF_MAX, SIZE_MAX) - len - 1) / 4 < nr_bad) + memory_full (SIZE_MAX); + up = utf8_str = xmalloc (len + nr_bad * 4 + 1); p = (unsigned char *)str; while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read, @@ -3296,8 +3300,8 @@ static int scroll_bar_width_for_theme; static struct { GtkWidget **widgets; - int max_size; - int used; + ptrdiff_t max_size; + ptrdiff_t used; } id_to_widget; /* Grow this much every time we need to allocate more */ @@ -3306,15 +3310,20 @@ static struct /* Store the widget pointer W in id_to_widget and return the integer index. */ -static int +static ptrdiff_t xg_store_widget_in_map (GtkWidget *w) { - int i; + ptrdiff_t i; if (id_to_widget.max_size == id_to_widget.used) { - int new_size = id_to_widget.max_size + ID_TO_WIDGET_INCR; + ptrdiff_t new_size; + ptrdiff_t lim = min (TYPE_MAXIMUM (Window), + min (PTRDIFF_MAX, SIZE_MAX) / sizeof (GtkWidget *)); + if (lim - ID_TO_WIDGET_INCR < id_to_widget.max_size) + memory_full (SIZE_MAX); + new_size = id_to_widget.max_size + ID_TO_WIDGET_INCR; id_to_widget.widgets = xrealloc (id_to_widget.widgets, sizeof (GtkWidget *)*new_size); @@ -3345,7 +3354,7 @@ xg_store_widget_in_map (GtkWidget *w) Called when scroll bar is destroyed. */ static void -xg_remove_widget_from_map (int idx) +xg_remove_widget_from_map (ptrdiff_t idx) { if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0) { @@ -3357,7 +3366,7 @@ xg_remove_widget_from_map (int idx) /* Get the widget pointer at IDX from id_to_widget. */ static GtkWidget * -xg_get_widget_from_map (int idx) +xg_get_widget_from_map (ptrdiff_t idx) { if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0) return id_to_widget.widgets[idx]; @@ -3396,10 +3405,10 @@ xg_get_default_scrollbar_width (void) /* Return the scrollbar id for X Window WID on display DPY. Return -1 if WID not in id_to_widget. */ -int +ptrdiff_t xg_get_scroll_id_for_window (Display *dpy, Window wid) { - int idx; + ptrdiff_t idx; GtkWidget *w; w = xg_win_to_widget (dpy, wid); @@ -3421,7 +3430,7 @@ xg_get_scroll_id_for_window (Display *dpy, Window wid) static void xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data) { - int id = (intptr_t) data; + intptr_t id = (intptr_t) data; xg_remove_widget_from_map (id); } @@ -3496,7 +3505,7 @@ xg_create_scroll_bar (FRAME_PTR f, /* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */ void -xg_remove_scroll_bar (FRAME_PTR f, int scrollbar_id) +xg_remove_scroll_bar (FRAME_PTR f, ptrdiff_t scrollbar_id) { GtkWidget *w = xg_get_widget_from_map (scrollbar_id); if (w) @@ -3515,7 +3524,7 @@ xg_remove_scroll_bar (FRAME_PTR f, int scrollbar_id) void xg_update_scrollbar_pos (FRAME_PTR f, - int scrollbar_id, + ptrdiff_t scrollbar_id, int top, int left, int width, @@ -4429,7 +4438,7 @@ update_frame_tool_bar (FRAME_PTR f) int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); int idx; - int img_id; + ptrdiff_t img_id; int icon_size = 0; struct image *img = NULL; Lisp_Object image; diff --git a/src/gtkutil.h b/src/gtkutil.h index 769e56da917..2dfb3a5ed6c 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -114,17 +114,17 @@ extern int xg_event_is_for_menubar (FRAME_PTR f, XEvent *event); extern int xg_have_tear_offs (void); -extern int xg_get_scroll_id_for_window (Display *dpy, Window wid); +extern ptrdiff_t xg_get_scroll_id_for_window (Display *dpy, Window wid); extern void xg_create_scroll_bar (FRAME_PTR f, struct scroll_bar *bar, GCallback scroll_callback, GCallback end_callback, const char *scroll_bar_name); -extern void xg_remove_scroll_bar (FRAME_PTR f, int scrollbar_id); +extern void xg_remove_scroll_bar (FRAME_PTR f, ptrdiff_t scrollbar_id); extern void xg_update_scrollbar_pos (FRAME_PTR f, - int scrollbar_id, + ptrdiff_t scrollbar_id, int top, int left, int width, @@ -185,4 +185,3 @@ extern int xg_ignore_gtk_scrollbar; #endif /* USE_GTK */ #endif /* GTKUTIL_H */ - diff --git a/src/image.c b/src/image.c index fb1d825fa54..d2a71637fed 100644 --- a/src/image.c +++ b/src/image.c @@ -196,7 +196,7 @@ x_bitmap_width (FRAME_PTR f, ptrdiff_t id) int x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id) { - return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; + return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; } #endif @@ -218,9 +218,9 @@ x_allocate_bitmap_record (FRAME_PTR f) if (dpyinfo->bitmaps == NULL) { - dpyinfo->bitmaps_size = 10; dpyinfo->bitmaps - = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record)); + = (Bitmap_Record *) xmalloc (10 * sizeof (Bitmap_Record)); + dpyinfo->bitmaps_size = 10; dpyinfo->bitmaps_last = 1; return 1; } @@ -235,17 +235,18 @@ x_allocate_bitmap_record (FRAME_PTR f) if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Bitmap_Record) / 2 < dpyinfo->bitmaps_size) memory_full (SIZE_MAX); - dpyinfo->bitmaps_size *= 2; dpyinfo->bitmaps = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps, - dpyinfo->bitmaps_size * sizeof (Bitmap_Record)); + (dpyinfo->bitmaps_size + * (2 * sizeof (Bitmap_Record)))); + dpyinfo->bitmaps_size *= 2; return ++dpyinfo->bitmaps_last; } /* Add one reference to the reference count of the bitmap with id ID. */ void -x_reference_bitmap (FRAME_PTR f, int id) +x_reference_bitmap (FRAME_PTR f, ptrdiff_t id) { ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount; } @@ -807,29 +808,30 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, break; case IMAGE_POSITIVE_INTEGER_VALUE: - if (!INTEGERP (value) || XINT (value) <= 0) + if (! RANGED_INTEGERP (1, value, INT_MAX)) return 0; break; case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR: - if (INTEGERP (value) && XINT (value) >= 0) + if (RANGED_INTEGERP (1, value, INT_MAX)) break; if (CONSP (value) - && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value)) - && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0) + && RANGED_INTEGERP (1, XCAR (value), INT_MAX) + && RANGED_INTEGERP (1, XCDR (value), INT_MAX)) break; return 0; case IMAGE_ASCENT_VALUE: if (SYMBOLP (value) && EQ (value, Qcenter)) break; - else if (INTEGERP (value) - && XINT (value) >= 0 - && XINT (value) <= 100) + else if (RANGED_INTEGERP (0, value, 100)) break; return 0; case IMAGE_NON_NEGATIVE_INTEGER_VALUE: + /* Unlike the other integer-related cases, this one does not + verify that VALUE fits in 'int'. This is because callers + want EMACS_INT. */ if (!INTEGERP (value) || XINT (value) < 0) return 0; break; @@ -849,7 +851,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, break; case IMAGE_INTEGER_VALUE: - if (!INTEGERP (value)) + if (! TYPE_RANGED_INTEGERP (int, value)) return 0; break; @@ -919,7 +921,7 @@ or omitted means use the selected frame. */) if (valid_image_p (spec)) { struct frame *f = check_x_frame (frame); - int id = lookup_image (f, spec); + ptrdiff_t id = lookup_image (f, spec); struct image *img = IMAGE_FROM_ID (f, id); int width = img->width + 2 * img->hmargin; int height = img->height + 2 * img->vmargin; @@ -949,7 +951,7 @@ or omitted means use the selected frame. */) if (valid_image_p (spec)) { struct frame *f = check_x_frame (frame); - int id = lookup_image (f, spec); + ptrdiff_t id = lookup_image (f, spec); struct image *img = IMAGE_FROM_ID (f, id); if (img->mask) mask = Qt; @@ -972,7 +974,7 @@ or omitted means use the selected frame. */) if (valid_image_p (spec)) { struct frame *f = check_x_frame (frame); - int id = lookup_image (f, spec); + ptrdiff_t id = lookup_image (f, spec); struct image *img = IMAGE_FROM_ID (f, id); ext = img->lisp_data; } @@ -1121,7 +1123,7 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice) ascent = height / 2; } else - ascent = (int) (height * img->ascent / 100.0); + ascent = height * (img->ascent / 100.0); return ascent; } @@ -1367,11 +1369,12 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name, { /* This isn't called frequently so we get away with simply reallocating the color vector to the needed size, here. */ - ++img->ncolors; + ptrdiff_t ncolors = img->ncolors + 1; img->colors = (unsigned long *) xrealloc (img->colors, - img->ncolors * sizeof *img->colors); - img->colors[img->ncolors - 1] = color.pixel; + ncolors * sizeof *img->colors); + img->colors[ncolors - 1] = color.pixel; + img->ncolors = ncolors; result = color.pixel; } else @@ -1399,8 +1402,9 @@ make_image_cache (void) int size; memset (c, 0, sizeof *c); - c->size = 50; - c->images = (struct image **) xmalloc (c->size * sizeof *c->images); + size = 50; + c->images = (struct image **) xmalloc (size * sizeof *c->images); + c->size = size; size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets; c->buckets = (struct image **) xmalloc (size); memset (c->buckets, 0, size); @@ -1466,7 +1470,7 @@ free_image_cache (struct frame *f) struct image_cache *c = FRAME_IMAGE_CACHE (f); if (c) { - int i; + ptrdiff_t i; /* Cache should not be referenced by any frame when freed. */ xassert (c->refcount == 0); @@ -1496,7 +1500,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter) if (c) { - int i, nfreed = 0; + ptrdiff_t i, nfreed = 0; /* Block input so that we won't be interrupted by a SIGIO while being in an inconsistent state. */ @@ -1520,8 +1524,8 @@ clear_image_cache (struct frame *f, Lisp_Object filter) { /* Free cache based on timestamp. */ EMACS_TIME t; - time_t old; - int delay, nimages = 0; + double old, delay; + ptrdiff_t nimages = 0; for (i = 0; i < c->used; ++i) if (c->images[i]) @@ -1529,9 +1533,10 @@ clear_image_cache (struct frame *f, Lisp_Object filter) /* If the number of cached images has grown unusually large, decrease the cache eviction delay (Bug#6230). */ - delay = XFASTINT (Vimage_cache_eviction_delay); + delay = XINT (Vimage_cache_eviction_delay); if (nimages > 40) - delay = max (1, 1600 * delay / (nimages*nimages)); + delay = 1600 * delay / nimages / nimages; + delay = max (delay, 1); EMACS_GET_TIME (t); old = EMACS_SECS (t) - delay; @@ -1707,7 +1712,7 @@ postprocess_image (struct frame *f, struct image *img) /* Return the id of image with Lisp specification SPEC on frame F. SPEC must be a valid Lisp image specification (see valid_image_p). */ -int +ptrdiff_t lookup_image (struct frame *f, Lisp_Object spec) { struct image *img; @@ -1766,15 +1771,12 @@ lookup_image (struct frame *f, Lisp_Object spec) img->ascent = CENTERED_IMAGE_ASCENT; margin = image_spec_value (spec, QCmargin, NULL); - if (INTEGERP (margin) && XINT (margin) >= 0) + if (INTEGERP (margin)) img->vmargin = img->hmargin = XFASTINT (margin); - else if (CONSP (margin) && INTEGERP (XCAR (margin)) - && INTEGERP (XCDR (margin))) + else if (CONSP (margin)) { - if (XINT (XCAR (margin)) > 0) - img->hmargin = XFASTINT (XCAR (margin)); - if (XINT (XCDR (margin)) > 0) - img->vmargin = XFASTINT (XCDR (margin)); + img->hmargin = XFASTINT (XCAR (margin)); + img->vmargin = XFASTINT (XCDR (margin)); } relief = image_spec_value (spec, QCrelief, NULL); @@ -1821,7 +1823,7 @@ static void cache_image (struct frame *f, struct image *img) { struct image_cache *c = FRAME_IMAGE_CACHE (f); - int i; + ptrdiff_t i; /* Find a free slot in c->images. */ for (i = 0; i < c->used; ++i) @@ -1833,9 +1835,10 @@ cache_image (struct frame *f, struct image *img) { if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->images / 2 < c->size) memory_full (SIZE_MAX); + c->images = + (struct image **) xrealloc (c->images, + c->size * (2 * sizeof *c->images)); c->size *= 2; - c->images = (struct image **) xrealloc (c->images, - c->size * sizeof *c->images); } /* Add IMG to c->images, and assign IMG an id. */ @@ -1875,7 +1878,7 @@ mark_image_cache (struct image_cache *c) { if (c) { - int i; + ptrdiff_t i; for (i = 0; i < c->used; ++i) if (c->images[i]) mark_image (c->images[i]); @@ -2072,7 +2075,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, DWORD err = GetLastError (); Lisp_Object errcode; /* All system errors are < 10000, so the following is safe. */ - XSETINT (errcode, (int) err); + XSETINT (errcode, err); image_error ("Unable to create bitmap, error code %d", errcode, Qnil); x_destroy_x_image (*ximg); return 0; @@ -2351,7 +2354,7 @@ xbm_image_p (Lisp_Object object) else { Lisp_Object data; - EMACS_INT width, height; + int width, height; /* Entries for `:width', `:height' and `:data' must be present. */ if (!kw[XBM_WIDTH].count @@ -3583,9 +3586,12 @@ xpm_load (struct frame *f, struct image *img) #endif /* HAVE_NTGUI */ /* Remember allocated colors. */ - img->ncolors = attrs.nalloc_pixels; + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *img->colors + < attrs.nalloc_pixels) + memory_full (SIZE_MAX); img->colors = (unsigned long *) xmalloc (img->ncolors * sizeof *img->colors); + img->ncolors = attrs.nalloc_pixels; for (i = 0; i < attrs.nalloc_pixels; ++i) { img->colors[i] = attrs.alloc_pixels[i]; @@ -3809,8 +3815,8 @@ xpm_get_color_table_h (Lisp_Object color_table, int chars_len) { struct Lisp_Hash_Table *table = XHASH_TABLE (color_table); - int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len), - NULL); + ptrdiff_t i = + hash_lookup (table, make_unibyte_string (chars_start, chars_len), NULL); return i >= 0 ? HASH_VALUE (table, i) : Qnil; } @@ -4159,6 +4165,12 @@ static struct ct_color **ct_table; /* Number of entries in the color table. */ static int ct_colors_allocated; +enum +{ + ct_colors_allocated_max = + min (INT_MAX, + min (PTRDIFF_MAX, SIZE_MAX) / sizeof (unsigned long)) +}; /* Initialize the color table. */ @@ -4245,7 +4257,14 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) XColor color; Colormap cmap; int rc; +#else + COLORREF color; +#endif + + if (ct_colors_allocated_max <= ct_colors_allocated) + return FRAME_FOREGROUND_PIXEL (f); +#ifdef HAVE_X_WINDOWS color.red = r; color.green = g; color.blue = b; @@ -4267,7 +4286,6 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) return FRAME_FOREGROUND_PIXEL (f); #else - COLORREF color; #ifdef HAVE_NTGUI color = PALETTERGB (r, g, b); #else @@ -4308,6 +4326,9 @@ lookup_pixel_color (struct frame *f, unsigned long pixel) Colormap cmap; int rc; + if (ct_colors_allocated_max <= ct_colors_allocated) + return FRAME_FOREGROUND_PIXEL (f); + #ifdef HAVE_X_WINDOWS cmap = FRAME_X_COLORMAP (f); color.pixel = pixel; @@ -4446,7 +4467,9 @@ x_to_xcolors (struct frame *f, struct image *img, int rgb_p) HGDIOBJ prev; #endif /* HAVE_NTGUI */ - colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors); + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height) + memory_full (SIZE_MAX); + colors = (XColor *) xmalloc (sizeof *colors * img->width * img->height); #ifndef HAVE_NTGUI /* Get the X image IMG->pixmap. */ @@ -4598,7 +4621,9 @@ x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjus #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X)) - new = (XColor *) xmalloc (img->width * img->height * sizeof *new); + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height) + memory_full (SIZE_MAX); + new = (XColor *) xmalloc (sizeof *new * img->width * img->height); for (y = 0; y < img->height; ++y) { @@ -5876,7 +5901,7 @@ png_load (struct frame *f, struct image *img) for (x = 0; x < width; ++x) { - unsigned r, g, b; + int r, g, b; r = *p++ << 8; g = *p++ << 8; @@ -6741,17 +6766,29 @@ tiff_size_of_memory (thandle_t data) } +static void tiff_handler (const char *, const char *, const char *, va_list) + ATTRIBUTE_FORMAT_PRINTF (3, 0); +static void +tiff_handler (const char *log_format, const char *title, + const char *format, va_list ap) +{ + /* doprnt is not suitable here, as TIFF handlers are called from + libtiff and are passed arbitrary printf directives. Instead, use + vsnprintf, taking care to be portable to nonstandard environments + where vsnprintf returns -1 on buffer overflow. Since it's just a + log entry, it's OK to truncate it. */ + char buf[4000]; + int len = vsnprintf (buf, sizeof buf, format, ap); + add_to_log (log_format, build_string (title), + make_string (buf, max (0, min (len, sizeof buf - 1)))); +} + static void tiff_error_handler (const char *, const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (2, 0); static void tiff_error_handler (const char *title, const char *format, va_list ap) { - char buf[512]; - int len; - - len = sprintf (buf, "TIFF error: %s ", title); - vsprintf (buf + len, format, ap); - add_to_log (buf, Qnil, Qnil); + tiff_handler ("TIFF error: %s %s", title, format, ap); } @@ -6760,12 +6797,7 @@ static void tiff_warning_handler (const char *, const char *, va_list) static void tiff_warning_handler (const char *title, const char *format, va_list ap) { - char buf[512]; - int len; - - len = sprintf (buf, "TIFF warning: %s ", title); - vsprintf (buf + len, format, ap); - add_to_log (buf, Qnil, Qnil); + tiff_handler ("TIFF warning: %s %s", title, format, ap); } @@ -6841,8 +6873,9 @@ tiff_load (struct frame *f, struct image *img) image = image_spec_value (img->spec, QCindex, NULL); if (INTEGERP (image)) { - int ino = XFASTINT (image); - if (!fn_TIFFSetDirectory (tiff, ino)) + EMACS_INT ino = XFASTINT (image); + if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t) + && fn_TIFFSetDirectory (tiff, ino))) { image_error ("Invalid image number `%s' in image `%s'", image, img->spec); @@ -7141,7 +7174,7 @@ gif_load (struct frame *f, struct image *img) Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL); Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL); unsigned long bgcolor = 0; - int idx; + EMACS_INT idx; if (NILP (specified_data)) { @@ -7371,7 +7404,7 @@ gif_load (struct frame *f, struct image *img) img->lisp_data = Qnil; if (gif->SavedImages[idx].ExtensionBlockCount > 0) { - unsigned int delay = 0; + int delay = 0; ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks; for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++) /* Append (... FUNCTION "BYTES") */ @@ -7392,7 +7425,7 @@ gif_load (struct frame *f, struct image *img) if (delay) img->lisp_data = Fcons (Qdelay, - Fcons (make_float (((double) delay) * 0.01), + Fcons (make_float (delay / 100.0), img->lisp_data)); } @@ -7568,10 +7601,10 @@ imagemagick_load_image (struct frame *f, struct image *img, Lisp_Object image; Lisp_Object value; Lisp_Object crop; - long ino; + EMACS_INT ino; int desired_width, desired_height; double rotation; - int imagemagick_rendermethod; + EMACS_INT imagemagick_rendermethod; int pixelwidth; ImageInfo *image_info; ExceptionInfo *exception; @@ -7598,7 +7631,7 @@ imagemagick_load_image (struct frame *f, struct image *img, status = MagickPingImageBlob (ping_wand, contents, size); } - if (ino >= MagickGetNumberImages (ping_wand)) + if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand))) { image_error ("Invalid image number `%s' in image `%s'", image, img->spec); @@ -7673,28 +7706,28 @@ imagemagick_load_image (struct frame *f, struct image *img, efficient. */ crop = image_spec_value (img->spec, QCcrop, NULL); - if (CONSP (crop) && INTEGERP (XCAR (crop))) + if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop))) { /* After some testing, it seems MagickCropImage is the fastest crop function in ImageMagick. This crop function seems to do less copying than the alternatives, but it still reads the entire image into memory - before croping, which is aparently difficult to avoid when using + before cropping, which is apparently difficult to avoid when using imagemagick. */ - int w, h; - w = XFASTINT (XCAR (crop)); + size_t crop_width = XINT (XCAR (crop)); crop = XCDR (crop); - if (CONSP (crop) && INTEGERP (XCAR (crop))) + if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop))) { - h = XFASTINT (XCAR (crop)); + size_t crop_height = XINT (XCAR (crop)); crop = XCDR (crop); - if (CONSP (crop) && INTEGERP (XCAR (crop))) + if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop))) { - x = XFASTINT (XCAR (crop)); + ssize_t crop_x = XINT (XCAR (crop)); crop = XCDR (crop); - if (CONSP (crop) && INTEGERP (XCAR (crop))) + if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop))) { - y = XFASTINT (XCAR (crop)); - MagickCropImage (image_wand, w, h, x, y); + ssize_t crop_y = XINT (XCAR (crop)); + MagickCropImage (image_wand, crop_width, crop_height, + crop_x, crop_y); } } } @@ -7740,9 +7773,11 @@ imagemagick_load_image (struct frame *f, struct image *img, init_color_table (); imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type) - ? XFASTINT (Vimagemagick_render_type) : 0); + ? XINT (Vimagemagick_render_type) : 0); if (imagemagick_rendermethod == 0) { + size_t image_height; + /* Try to create a x pixmap to hold the imagemagick pixmap. */ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) @@ -7771,7 +7806,8 @@ imagemagick_load_image (struct frame *f, struct image *img, goto imagemagick_error; } - for (y = 0; y < (long) MagickGetImageHeight (image_wand); y++) + image_height = MagickGetImageHeight (image_wand); + for (y = 0; y < image_height; y++) { pixels = PixelGetNextIteratorRow (iterator, &width); if (pixels == (PixelWand **) NULL) @@ -8277,10 +8313,10 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. * { for (x = 0; x < width; ++x) { - unsigned red; - unsigned green; - unsigned blue; - unsigned opacity; + int red; + int green; + int blue; + int opacity; red = *pixels++; green = *pixels++; @@ -8461,7 +8497,8 @@ gs_image_p (Lisp_Object object) static int gs_load (struct frame *f, struct image *img) { - char buffer[100]; + uprintmax_t printnum1, printnum2; + char buffer[sizeof " " + INT_STRLEN_BOUND (printmax_t)]; Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width; Lisp_Object frame; double in_width, in_height; @@ -8473,16 +8510,19 @@ gs_load (struct frame *f, struct image *img) info. */ pt_width = image_spec_value (img->spec, QCpt_width, NULL); in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0; - img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx; + in_width *= FRAME_X_DISPLAY_INFO (f)->resx; pt_height = image_spec_value (img->spec, QCpt_height, NULL); in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0; - img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy; + in_height *= FRAME_X_DISPLAY_INFO (f)->resy; - if (!check_image_size (f, img->width, img->height)) + if (! (in_width <= INT_MAX && in_height <= INT_MAX + && check_image_size (f, in_width, in_height))) { image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); return 0; } + img->width = in_width; + img->height = in_height; /* Create the pixmap. */ xassert (img->pixmap == NO_PIXMAP); @@ -8507,14 +8547,14 @@ gs_load (struct frame *f, struct image *img) if successful. We do not record_unwind_protect here because other places in redisplay like calling window scroll functions don't either. Let the Lisp loader use `unwind-protect' instead. */ - sprintf (buffer, "%lu %lu", - (unsigned long) FRAME_X_WINDOW (f), - (unsigned long) img->pixmap); + printnum1 = FRAME_X_WINDOW (f); + printnum2 = img->pixmap; + sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2); window_and_pixmap_id = build_string (buffer); - sprintf (buffer, "%lu %lu", - FRAME_FOREGROUND_PIXEL (f), - FRAME_BACKGROUND_PIXEL (f)); + printnum1 = FRAME_FOREGROUND_PIXEL (f); + printnum2 = FRAME_BACKGROUND_PIXEL (f); + sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2); pixel_colors = build_string (buffer); XSETFRAME (frame, f); @@ -8539,7 +8579,8 @@ void x_kill_gs_process (Pixmap pixmap, struct frame *f) { struct image_cache *c = FRAME_IMAGE_CACHE (f); - int class, i; + int class; + ptrdiff_t i; struct image *img; /* Find the image containing PIXMAP. */ @@ -8643,7 +8684,7 @@ DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0, DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "") (Lisp_Object spec) { - int id = -1; + ptrdiff_t id = -1; if (valid_image_p (spec)) id = lookup_image (SELECTED_FRAME (), spec); diff --git a/src/indent.c b/src/indent.c index aaeaaf591ef..8a2117751aa 100644 --- a/src/indent.c +++ b/src/indent.c @@ -284,7 +284,7 @@ skip_invisible (EMACS_INT pos, EMACS_INT *next_boundary_p, EMACS_INT to, Lisp_Ob else \ { \ if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, ch))) \ - width = ASIZE (DISP_CHAR_VECTOR (dp, ch)); \ + width = sanitize_char_width (ASIZE (DISP_CHAR_VECTOR (dp, ch))); \ else \ width = CHAR_WIDTH (ch); \ } \ @@ -318,15 +318,6 @@ invalidate_current_column (void) last_known_column_point = 0; } -/* Return a non-outlandish value for the tab width. */ - -static int -sane_tab_width (void) -{ - EMACS_INT n = XFASTINT (BVAR (current_buffer, tab_width)); - return 0 < n && n <= 1000 ? n : 8; -} - EMACS_INT current_column (void) { @@ -335,7 +326,7 @@ current_column (void) register int tab_seen; EMACS_INT post_tab; register int c; - int tab_width = sane_tab_width (); + int tab_width = SANE_TAB_WIDTH (current_buffer); int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow)); register struct Lisp_Char_Table *dp = buffer_display_table (); @@ -515,7 +506,7 @@ check_display_width (EMACS_INT pos, EMACS_INT col, EMACS_INT *endpos) static void scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol) { - int tab_width = sane_tab_width (); + int tab_width = SANE_TAB_WIDTH (current_buffer); register int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow)); register struct Lisp_Char_Table *dp = buffer_display_table (); int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); @@ -732,7 +723,7 @@ string_display_width (Lisp_Object string, Lisp_Object beg, Lisp_Object end) register int tab_seen; int post_tab; register int c; - int tab_width = sane_tab_width (); + int tab_width = SANE_TAB_WIDTH (current_buffer); int ctl_arrow = !NILP (current_buffer->ctl_arrow); register struct Lisp_Char_Table *dp = buffer_display_table (); int b, e; @@ -808,7 +799,7 @@ The return value is COLUMN. */) { EMACS_INT mincol; register EMACS_INT fromcol; - int tab_width = sane_tab_width (); + int tab_width = SANE_TAB_WIDTH (current_buffer); CHECK_NUMBER (column); if (NILP (minimum)) @@ -867,7 +858,7 @@ static EMACS_INT position_indentation (register int pos_byte) { register EMACS_INT column = 0; - int tab_width = sane_tab_width (); + int tab_width = SANE_TAB_WIDTH (current_buffer); register unsigned char *p; register unsigned char *stop; unsigned char *start; @@ -1116,7 +1107,7 @@ compute_motion (EMACS_INT from, EMACS_INT fromvpos, EMACS_INT fromhpos, int did_ register EMACS_INT pos; EMACS_INT pos_byte; register int c = 0; - int tab_width = sane_tab_width (); + int tab_width = SANE_TAB_WIDTH (current_buffer); register int ctl_arrow = !NILP (BVAR (current_buffer, ctl_arrow)); register struct Lisp_Char_Table *dp = window_display_table (win); EMACS_INT selective diff --git a/src/keyboard.c b/src/keyboard.c index 7e144b80a09..622f7ca4482 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -435,16 +435,16 @@ static void (*keyboard_init_hook) (void); static int read_avail_input (int); static void get_input_pending (int *, int); static int readable_events (int); -static Lisp_Object read_char_x_menu_prompt (int, Lisp_Object *, +static Lisp_Object read_char_x_menu_prompt (ptrdiff_t, Lisp_Object *, Lisp_Object, int *); -static Lisp_Object read_char_minibuf_menu_prompt (int, int, +static Lisp_Object read_char_minibuf_menu_prompt (int, ptrdiff_t, Lisp_Object *); static Lisp_Object make_lispy_event (struct input_event *); #if defined (HAVE_MOUSE) || defined (HAVE_GPM) static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object, enum scroll_bar_part, Lisp_Object, Lisp_Object, - unsigned long); + Time); #endif static Lisp_Object modify_event_symbol (EMACS_INT, unsigned, Lisp_Object, Lisp_Object, const char *const *, @@ -1300,7 +1300,7 @@ some_mouse_moved (void) /* This is the actual command reading loop, sans error-handling encapsulation. */ -static int read_key_sequence (Lisp_Object *, size_t, Lisp_Object, +static int read_key_sequence (Lisp_Object *, int, Lisp_Object, int, int, int); void safe_run_hooks (Lisp_Object); static void adjust_point_for_property (EMACS_INT, int); @@ -2267,7 +2267,8 @@ do { if (polling_stopped_here) start_polling (); \ Value is t if we showed a menu and the user rejected it. */ Lisp_Object -read_char (int commandflag, int nmaps, Lisp_Object *maps, Lisp_Object prev_event, +read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, + Lisp_Object prev_event, int *used_mouse_menu, struct timeval *end_time) { volatile Lisp_Object c; @@ -7405,7 +7406,7 @@ menu_bar_items (Lisp_Object old) { /* The number of keymaps we're scanning right now, and the number of keymaps we have allocated space for. */ - int nmaps; + ptrdiff_t nmaps; /* maps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1] in the current keymaps, or nil where it is not a prefix. */ @@ -7413,7 +7414,7 @@ menu_bar_items (Lisp_Object old) Lisp_Object def, tail; - int mapno; + ptrdiff_t mapno; Lisp_Object oquit; /* In order to build the menus, we need to call the keymap @@ -7458,7 +7459,7 @@ menu_bar_items (Lisp_Object old) recognized when the menu-bar (or mode-line) is updated, which does not normally happen after every command. */ Lisp_Object tem; - int nminor; + ptrdiff_t nminor; nminor = current_minor_maps (NULL, &tmaps); maps = (Lisp_Object *) alloca ((nminor + 3) * sizeof (maps[0])); nmaps = 0; @@ -7962,7 +7963,7 @@ Lisp_Object tool_bar_items (Lisp_Object reuse, int *nitems) { Lisp_Object *maps; - int nmaps, i; + ptrdiff_t nmaps, i; Lisp_Object oquit; Lisp_Object *tmaps; @@ -8002,7 +8003,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems) recognized when the tool-bar (or mode-line) is updated, which does not normally happen after every command. */ Lisp_Object tem; - int nminor; + ptrdiff_t nminor; nminor = current_minor_maps (NULL, &tmaps); maps = (Lisp_Object *) alloca ((nminor + 3) * sizeof (maps[0])); nmaps = 0; @@ -8274,10 +8275,11 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item) Lisp_Object tcapt = PROP (TOOL_BAR_ITEM_CAPTION); const char *label = SYMBOLP (tkey) ? SSDATA (SYMBOL_NAME (tkey)) : ""; const char *capt = STRINGP (tcapt) ? SSDATA (tcapt) : ""; - EMACS_INT max_lbl = 2 * tool_bar_max_label_size; + ptrdiff_t max_lbl = + 2 * max (0, min (tool_bar_max_label_size, STRING_BYTES_BOUND / 2)); char *buf = (char *) xmalloc (max_lbl + 1); Lisp_Object new_lbl; - size_t caption_len = strlen (capt); + ptrdiff_t caption_len = strlen (capt); if (caption_len <= max_lbl && capt[0] != '\0') { @@ -8290,7 +8292,7 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item) if (strlen (label) <= max_lbl && label[0] != '\0') { - int j; + ptrdiff_t j; if (label != buf) strcpy (buf, label); @@ -8399,10 +8401,10 @@ append_tool_bar_item (void) and do auto-saving in the inner call of read_char. */ static Lisp_Object -read_char_x_menu_prompt (int nmaps, Lisp_Object *maps, Lisp_Object prev_event, - int *used_mouse_menu) +read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps, + Lisp_Object prev_event, int *used_mouse_menu) { - int mapno; + ptrdiff_t mapno; if (used_mouse_menu) *used_mouse_menu = 0; @@ -8430,7 +8432,7 @@ read_char_x_menu_prompt (int nmaps, Lisp_Object *maps, Lisp_Object prev_event, Lisp_Object *realmaps = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object)); Lisp_Object value; - int nmaps1 = 0; + ptrdiff_t nmaps1 = 0; /* Use the maps that are not nil. */ for (mapno = 0; mapno < nmaps; mapno++) @@ -8481,17 +8483,18 @@ read_char_x_menu_prompt (int nmaps, Lisp_Object *maps, Lisp_Object prev_event, We make this bigger when necessary, and never free it. */ static char *read_char_minibuf_menu_text; /* Size of that buffer. */ -static int read_char_minibuf_menu_width; +static ptrdiff_t read_char_minibuf_menu_width; static Lisp_Object -read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps) +read_char_minibuf_menu_prompt (int commandflag, + ptrdiff_t nmaps, Lisp_Object *maps) { - int mapno; + ptrdiff_t mapno; register Lisp_Object name; - int nlength; + ptrdiff_t nlength; /* FIXME: Use the minibuffer's frame width. */ - int width = FRAME_COLS (SELECTED_FRAME ()) - 4; - int idx = -1; + ptrdiff_t width = FRAME_COLS (SELECTED_FRAME ()) - 4; + ptrdiff_t idx = -1; int nobindings = 1; Lisp_Object rest, vector; char *menu; @@ -8516,16 +8519,13 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps) /* Make sure we have a big enough buffer for the menu text. */ width = max (width, SBYTES (name)); - if (read_char_minibuf_menu_text == 0) + if (STRING_BYTES_BOUND - 4 < width) + memory_full (SIZE_MAX); + if (width + 4 > read_char_minibuf_menu_width) { - read_char_minibuf_menu_width = width + 4; - read_char_minibuf_menu_text = (char *) xmalloc (width + 4); - } - else if (width + 4 > read_char_minibuf_menu_width) - { - read_char_minibuf_menu_width = width + 4; read_char_minibuf_menu_text = (char *) xrealloc (read_char_minibuf_menu_text, width + 4); + read_char_minibuf_menu_width = width + 4; } menu = read_char_minibuf_menu_text; @@ -8544,7 +8544,7 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps) while (1) { int notfirst = 0; - int i = nlength; + ptrdiff_t i = nlength; Lisp_Object obj; Lisp_Object orig_defn_macro; @@ -8643,7 +8643,7 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps) < width || !notfirst) { - int thiswidth; + ptrdiff_t thiswidth; /* Punctuate between strings. */ if (notfirst) @@ -8659,9 +8659,7 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps) if (! char_matches) { /* Add as much of string as fits. */ - thiswidth = SCHARS (desc); - if (thiswidth + i > width) - thiswidth = width - i; + thiswidth = min (SCHARS (desc), width - i); memcpy (menu + i, SDATA (desc), thiswidth); i += thiswidth; strcpy (menu + i, " = "); @@ -8669,9 +8667,7 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps) } /* Add as much of string as fits. */ - thiswidth = SCHARS (s); - if (thiswidth + i > width) - thiswidth = width - i; + thiswidth = min (SCHARS (s), width - i); memcpy (menu + i, SDATA (s), thiswidth); i += thiswidth; menu[i] = 0; @@ -8746,10 +8742,10 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps) NEXT may be the same array as CURRENT. */ static int -follow_key (Lisp_Object key, int nmaps, Lisp_Object *current, Lisp_Object *defs, - Lisp_Object *next) +follow_key (Lisp_Object key, ptrdiff_t nmaps, Lisp_Object *current, + Lisp_Object *defs, Lisp_Object *next) { - int i, first_binding; + ptrdiff_t i, first_binding; first_binding = nmaps; for (i = nmaps - 1; i >= 0; i--) @@ -8849,7 +8845,7 @@ access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt, The return value is non-zero if the remapping actually took place. */ static int -keyremap_step (Lisp_Object *keybuf, size_t bufsize, volatile keyremap *fkey, +keyremap_step (Lisp_Object *keybuf, int bufsize, volatile keyremap *fkey, int input, int doit, int *diff, Lisp_Object prompt) { Lisp_Object next, key; @@ -8871,7 +8867,7 @@ keyremap_step (Lisp_Object *keybuf, size_t bufsize, volatile keyremap *fkey, *diff = len - (fkey->end - fkey->start); - if (input + *diff >= bufsize) + if (bufsize - input <= *diff) error ("Key sequence too long"); /* Shift the keys that follow fkey->end. */ @@ -8942,7 +8938,7 @@ keyremap_step (Lisp_Object *keybuf, size_t bufsize, volatile keyremap *fkey, from the selected window's buffer. */ static int -read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt, +read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, int dont_downcase_last, int can_return_switch_frame, int fix_current_buffer) { @@ -8959,8 +8955,8 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt, /* The number of keymaps we're scanning right now, and the number of keymaps we have allocated space for. */ - int nmaps; - int nmaps_allocated = 0; + ptrdiff_t nmaps; + ptrdiff_t nmaps_allocated = 0; /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in the current keymaps. */ @@ -8984,7 +8980,7 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt, /* The index in submaps[] of the first keymap that has a binding for this key sequence. In other words, the lowest i such that submaps[i] is non-nil. */ - int first_binding; + ptrdiff_t first_binding; /* Index of the first key that has no binding. It is useless to try fkey.start larger than that. */ int first_unbound; @@ -9145,8 +9141,8 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt, } else { - int nminor; - int total; + ptrdiff_t nminor; + ptrdiff_t total; Lisp_Object *maps; nminor = current_minor_maps (0, &maps); @@ -9212,7 +9208,8 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt, echo_local_start and keys_local_start allow us to throw away just one key. */ int echo_local_start IF_LINT (= 0); - int keys_local_start, local_first_binding; + int keys_local_start; + ptrdiff_t local_first_binding; eassert (indec.end == t || (indec.end > t && indec.end <= mock_input)); eassert (indec.start <= indec.end); @@ -9549,7 +9546,7 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt, && (NILP (fake_prefixed_keys) || NILP (Fmemq (key, fake_prefixed_keys)))) { - if (t + 1 >= bufsize) + if (bufsize - t <= 1) error ("Key sequence too long"); keybuf[t] = posn; @@ -9630,7 +9627,7 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt, insert the dummy prefix event `menu-bar'. */ if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar)) { - if (t + 1 >= bufsize) + if (bufsize - t <= 1) error ("Key sequence too long"); keybuf[t] = posn; keybuf[t+1] = key; diff --git a/src/keyboard.h b/src/keyboard.h index 69c804c873d..d4339d0529b 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -440,7 +440,7 @@ struct input_event; extern Lisp_Object parse_modifiers (Lisp_Object); extern Lisp_Object reorder_modifiers (Lisp_Object); -extern Lisp_Object read_char (int, int, Lisp_Object *, Lisp_Object, +extern Lisp_Object read_char (int, ptrdiff_t, Lisp_Object *, Lisp_Object, int *, EMACS_TIME *); extern int parse_solitary_modifier (Lisp_Object symbol); diff --git a/src/keymap.c b/src/keymap.c index 0169276bef9..c968b14d903 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1403,7 +1403,7 @@ silly_event_symbol_error (Lisp_Object c) some systems, static gets macro-defined to be the empty string. Ickypoo. */ static Lisp_Object *cmm_modes = NULL, *cmm_maps = NULL; -static int cmm_size = 0; +static ptrdiff_t cmm_size = 0; /* Store a pointer to an array of the currently active minor modes in *modeptr, a pointer to an array of the keymaps of the currently @@ -1423,10 +1423,10 @@ static int cmm_size = 0; loop. Instead, we'll use realloc/malloc and silently truncate the list, let the key sequence be read, and hope some other piece of code signals the error. */ -int +ptrdiff_t current_minor_maps (Lisp_Object **modeptr, Lisp_Object **mapptr) { - int i = 0; + ptrdiff_t i = 0; int list_number = 0; Lisp_Object alist, assoc, var, val; Lisp_Object emulation_alists; @@ -1469,9 +1469,16 @@ current_minor_maps (Lisp_Object **modeptr, Lisp_Object **mapptr) if (i >= cmm_size) { - int newsize, allocsize; + ptrdiff_t newsize, allocsize; Lisp_Object *newmodes, *newmaps; + /* Check for size calculation overflow. Other code + (e.g., read_key_sequence) adds 3 to the count + later, so subtract 3 from the limit here. */ + if (min (PTRDIFF_MAX, SIZE_MAX) / (2 * sizeof *newmodes) - 3 + < cmm_size) + break; + newsize = cmm_size == 0 ? 30 : cmm_size * 2; allocsize = newsize * sizeof *newmodes; diff --git a/src/keymap.h b/src/keymap.h index 2c826b64e1f..ec9d4cadbb1 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -38,7 +38,7 @@ extern Lisp_Object get_keymap (Lisp_Object, int, int); EXFUN (Fset_keymap_parent, 2); extern int describe_map_tree (Lisp_Object, int, Lisp_Object, Lisp_Object, const char *, int, int, int, int); -extern int current_minor_maps (Lisp_Object **, Lisp_Object **); +extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **); extern void initial_define_key (Lisp_Object, int, const char *); extern void initial_define_lispy_key (Lisp_Object, const char *, const char *); extern void syms_of_keymap (void); diff --git a/src/lisp.h b/src/lisp.h index 1e141dbb5d0..267bfe1b21f 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1704,6 +1704,11 @@ typedef struct { #define NUMBERP(x) (INTEGERP (x) || FLOATP (x)) #define NATNUMP(x) (INTEGERP (x) && XINT (x) >= 0) +#define RANGED_INTEGERP(lo, x, hi) \ + (INTEGERP (x) && (lo) <= XINT (x) && XINT (x) <= (hi)) +#define TYPE_RANGED_INTEGERP(type, x) \ + RANGED_INTEGERP (TYPE_MINIMUM (type), x, TYPE_MAXIMUM (type)) + #define INTEGERP(x) (LISP_INT_TAG_P (XTYPE ((x)))) #define SYMBOLP(x) (XTYPE ((x)) == Lisp_Symbol) #define MISCP(x) (XTYPE ((x)) == Lisp_Misc) @@ -2551,6 +2556,7 @@ extern void syms_of_syntax (void); /* Defined in fns.c */ extern Lisp_Object QCrehash_size, QCrehash_threshold; +enum { NEXT_ALMOST_PRIME_LIMIT = 11 }; extern EMACS_INT next_almost_prime (EMACS_INT); extern Lisp_Object larger_vector (Lisp_Object, EMACS_INT, Lisp_Object); extern void sweep_weak_hash_tables (void); @@ -2562,8 +2568,8 @@ EMACS_UINT sxhash (Lisp_Object, int); Lisp_Object make_hash_table (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); -EMACS_INT hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *); -EMACS_INT hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object, +ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *); +ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object, EMACS_UINT); void init_weak_hash_tables (void); extern void init_fns (void); diff --git a/src/lread.c b/src/lread.c index 78ff195e990..f2a52780a0c 100644 --- a/src/lread.c +++ b/src/lread.c @@ -2613,14 +2613,14 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list) if (saved_doc_string_size == 0) { + saved_doc_string = (char *) xmalloc (nskip + extra); saved_doc_string_size = nskip + extra; - saved_doc_string = (char *) xmalloc (saved_doc_string_size); } if (nskip > saved_doc_string_size) { - saved_doc_string_size = nskip + extra; saved_doc_string = (char *) xrealloc (saved_doc_string, - saved_doc_string_size); + nskip + extra); + saved_doc_string_size = nskip + extra; } saved_doc_string_position = file_tell (instream); @@ -2883,7 +2883,8 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list) if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size) memory_full (SIZE_MAX); read_buffer = (char *) xrealloc (read_buffer, - read_buffer_size *= 2); + read_buffer_size * 2); + read_buffer_size *= 2; p = read_buffer + offset; end = read_buffer + read_buffer_size; } @@ -3026,7 +3027,8 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list) if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size) memory_full (SIZE_MAX); read_buffer = (char *) xrealloc (read_buffer, - read_buffer_size *= 2); + read_buffer_size * 2); + read_buffer_size *= 2; p = read_buffer + offset; end = read_buffer + read_buffer_size; } @@ -3056,7 +3058,8 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list) if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size) memory_full (SIZE_MAX); read_buffer = (char *) xrealloc (read_buffer, - read_buffer_size *= 2); + read_buffer_size * 2); + read_buffer_size *= 2; p = read_buffer + offset; end = read_buffer + read_buffer_size; } @@ -3938,6 +3941,7 @@ void init_obarray (void) { Lisp_Object oblength; + ptrdiff_t size = 100 + MAX_MULTIBYTE_LENGTH; XSETFASTINT (oblength, OBARRAY_SIZE); @@ -3970,8 +3974,8 @@ init_obarray (void) DEFSYM (Qvariable_documentation, "variable-documentation"); - read_buffer_size = 100 + MAX_MULTIBYTE_LENGTH; - read_buffer = (char *) xmalloc (read_buffer_size); + read_buffer = (char *) xmalloc (size); + read_buffer_size = size; } void diff --git a/src/macros.c b/src/macros.c index 60f30c3fbbe..f6cd3a3ccad 100644 --- a/src/macros.c +++ b/src/macros.c @@ -62,9 +62,9 @@ macro before appending to it. */) if (!current_kboard->kbd_macro_buffer) { - current_kboard->kbd_macro_bufsize = 30; current_kboard->kbd_macro_buffer = (Lisp_Object *)xmalloc (30 * sizeof (Lisp_Object)); + current_kboard->kbd_macro_bufsize = 30; } update_mode_lines++; if (NILP (append)) @@ -202,7 +202,7 @@ store_kbd_macro_char (Lisp_Object c) if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *kb->kbd_macro_buffer / 2 < kb->kbd_macro_bufsize) memory_full (SIZE_MAX); - nbytes = kb->kbd_macro_bufsize * 2 * sizeof *kb->kbd_macro_buffer; + nbytes = kb->kbd_macro_bufsize * (2 * sizeof *kb->kbd_macro_buffer); kb->kbd_macro_buffer = (Lisp_Object *) xrealloc (kb->kbd_macro_buffer, nbytes); kb->kbd_macro_bufsize *= 2; diff --git a/src/minibuf.c b/src/minibuf.c index 7e59cf157b5..30082af9037 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -261,7 +261,10 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, if (len == size) { if (STRING_BYTES_BOUND / 2 < size) - memory_full (SIZE_MAX); + { + xfree (line); + memory_full (SIZE_MAX); + } size *= 2; line = (char *) xrealloc (line, size); } @@ -1723,7 +1726,7 @@ the values STRING, PREDICATE and `lambda'. */) (Lisp_Object string, Lisp_Object collection, Lisp_Object predicate) { Lisp_Object regexps, tail, tem = Qnil; - EMACS_INT i = 0; + ptrdiff_t i = 0; CHECK_STRING (string); diff --git a/src/nsmenu.m b/src/nsmenu.m index 6bde229ed4d..951282910ac 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1014,7 +1014,7 @@ update_frame_tool_bar (FRAME_PTR f) BOOL enabled_p = !NILP (TOOLPROP (TOOL_BAR_ITEM_ENABLED_P)); BOOL selected_p = !NILP (TOOLPROP (TOOL_BAR_ITEM_SELECTED_P)); int idx; - int img_id; + ptrdiff_t img_id; struct image *img; Lisp_Object image; Lisp_Object helpObj; diff --git a/src/nsterm.h b/src/nsterm.h index 6ea9161c922..5bbc5329aa2 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -416,8 +416,8 @@ struct ns_bitmap_record /* this to map between emacs color indices and NSColor objects */ struct ns_color_table { - unsigned int size; - unsigned int avail; + ptrdiff_t size; + ptrdiff_t avail; #ifdef __OBJC__ NSColor **colors; NSMutableSet *empty_indices; diff --git a/src/nsterm.m b/src/nsterm.m index d4b1a3f8473..2ce996dc82f 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1341,7 +1341,7 @@ unsigned long ns_index_color (NSColor *color, struct frame *f) { struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table; - int idx; + ptrdiff_t idx; NSNumber *index; if (!color_table->colors) @@ -1356,7 +1356,7 @@ ns_index_color (NSColor *color, struct frame *f) /* do we already have this color ? */ { - int i; + ptrdiff_t i; for (i = 1; i < color_table->avail; i++) { if (color_table->colors[i] && [color_table->colors[i] isEqual: color]) @@ -1371,16 +1371,23 @@ ns_index_color (NSColor *color, struct frame *f) { index = [color_table->empty_indices anyObject]; [color_table->empty_indices removeObject: index]; - idx = [index unsignedIntValue]; + idx = [index unsignedLongValue]; } else { if (color_table->avail == color_table->size) { - color_table->size += NS_COLOR_CAPACITY; + ptrdiff_t size; + ptrdiff_t size_max = + min (ULONG_MAX, + min (PTRDIFF_MAX, SIZE_MAX) / sizeof (NSColor *)); + if (size_max - NS_COLOR_CAPACITY < color_table->size) + memory_full (SIZE_MAX); + size = color_table->size + NS_COLOR_CAPACITY; color_table->colors = (NSColor **)xrealloc (color_table->colors, - color_table->size * sizeof (NSColor *)); + size * sizeof (NSColor *)); + color_table->size = size; } idx = color_table->avail++; } @@ -2321,7 +2328,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, if (!img) { unsigned short *bits = p->bits + p->dh; - int len = 8 * p->h/8; + int len = p->h; int i; unsigned char *cbits = xmalloc (len); @@ -4857,7 +4864,7 @@ ns_term_shutdown (int sig) } } - + #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 /* if we get here we should send the key for input manager processing */ if (firstTime && [[NSInputManager currentInputManager] diff --git a/src/process.c b/src/process.c index 236c27e5c3a..31359a1f1f2 100644 --- a/src/process.c +++ b/src/process.c @@ -3567,6 +3567,12 @@ format; see the description of ADDRESS in `make-network-process'. */) return Qnil; again: + if (min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX)) / sizeof *ifreqs - 25 + < ifaces) + { + xfree (ifreqs); + memory_full (SIZE_MAX); + } ifaces += 25; buf_size = ifaces * sizeof (ifreqs[0]); ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size); diff --git a/src/region-cache.c b/src/region-cache.c index d701f4d71b0..e6cec96171d 100644 --- a/src/region-cache.c +++ b/src/region-cache.c @@ -247,11 +247,16 @@ move_cache_gap (struct region_cache *c, EMACS_INT pos, EMACS_INT min_size) if (gap_len < min_size) { EMACS_INT i; + ptrdiff_t cache_len_max = + min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->boundaries; + ptrdiff_t min_size_max = cache_len_max - c->cache_len; - /* Always make at least NEW_CACHE_GAP elements, as long as we're - expanding anyway. */ - if (min_size < NEW_CACHE_GAP) - min_size = NEW_CACHE_GAP; + if (min_size_max < min_size) + memory_full (SIZE_MAX); + + /* Unless running out of space, make at least NEW_CACHE_GAP + elements, as long as we're expanding anyway. */ + min_size = max (min_size, min (min_size_max, NEW_CACHE_GAP)); c->boundaries = (struct boundary *) xrealloc (c->boundaries, diff --git a/src/scroll.c b/src/scroll.c index 6291936a541..9184919f0ce 100644 --- a/src/scroll.c +++ b/src/scroll.c @@ -969,32 +969,21 @@ do_line_insertion_deletion_costs (FRAME_PTR frame, const char *cleanup_string, int coefficient) { - if (FRAME_INSERT_COST (frame) != 0) - { - FRAME_INSERT_COST (frame) = - (int *) xrealloc (FRAME_INSERT_COST (frame), - FRAME_LINES (frame) * sizeof (int)); - FRAME_DELETEN_COST (frame) = - (int *) xrealloc (FRAME_DELETEN_COST (frame), - FRAME_LINES (frame) * sizeof (int)); - FRAME_INSERTN_COST (frame) = - (int *) xrealloc (FRAME_INSERTN_COST (frame), - FRAME_LINES (frame) * sizeof (int)); - FRAME_DELETE_COST (frame) = - (int *) xrealloc (FRAME_DELETE_COST (frame), - FRAME_LINES (frame) * sizeof (int)); - } - else - { - FRAME_INSERT_COST (frame) = - (int *) xmalloc (FRAME_LINES (frame) * sizeof (int)); - FRAME_DELETEN_COST (frame) = - (int *) xmalloc (FRAME_LINES (frame) * sizeof (int)); - FRAME_INSERTN_COST (frame) = - (int *) xmalloc (FRAME_LINES (frame) * sizeof (int)); - FRAME_DELETE_COST (frame) = - (int *) xmalloc (FRAME_LINES (frame) * sizeof (int)); - } + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < FRAME_LINES (frame)) + memory_full (SIZE_MAX); + + FRAME_INSERT_COST (frame) = + (int *) xrealloc (FRAME_INSERT_COST (frame), + FRAME_LINES (frame) * sizeof (int)); + FRAME_DELETEN_COST (frame) = + (int *) xrealloc (FRAME_DELETEN_COST (frame), + FRAME_LINES (frame) * sizeof (int)); + FRAME_INSERTN_COST (frame) = + (int *) xrealloc (FRAME_INSERTN_COST (frame), + FRAME_LINES (frame) * sizeof (int)); + FRAME_DELETE_COST (frame) = + (int *) xrealloc (FRAME_DELETE_COST (frame), + FRAME_LINES (frame) * sizeof (int)); ins_del_costs (frame, ins_line_string, multi_ins_string, diff --git a/src/search.c b/src/search.c index a56df784cd2..79ef8b046df 100644 --- a/src/search.c +++ b/src/search.c @@ -2648,6 +2648,8 @@ since only regular expressions have distinguished subexpressions. */) int really_changed = 0; substed_alloc_size = length * 2 + 100; + if (min (PTRDIFF_MAX, SIZE_MAX) - 1 < substed_alloc_size) + memory_full (SIZE_MAX); substed = (unsigned char *) xmalloc (substed_alloc_size + 1); substed_len = 0; @@ -2736,6 +2738,13 @@ since only regular expressions have distinguished subexpressions. */) /* Make sure SUBSTED is big enough. */ if (substed_len + add_len >= substed_alloc_size) { + ptrdiff_t add_len_max = + min (PTRDIFF_MAX, SIZE_MAX) - 1 - 500 - substed_len; + if (add_len_max < add_len) + { + xfree (substed); + memory_full (SIZE_MAX); + } substed_alloc_size = substed_len + add_len + 500; substed = (unsigned char *) xrealloc (substed, substed_alloc_size + 1); @@ -2973,7 +2982,7 @@ LIST should have been created by calling `match-data' previously. If optional arg RESEAT is non-nil, make markers on LIST point nowhere. */) (register Lisp_Object list, Lisp_Object reseat) { - register int i; + ptrdiff_t i; register Lisp_Object marker; if (running_asynch_code) @@ -2987,10 +2996,13 @@ If optional arg RESEAT is non-nil, make markers on LIST point nowhere. */) /* Allocate registers if they don't already exist. */ { - int length = XFASTINT (Flength (list)) / 2; + ptrdiff_t length = XFASTINT (Flength (list)) / 2; if (length > search_regs.num_regs) { + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (regoff_t) < length) + memory_full (SIZE_MAX); + if (search_regs.num_regs == 0) { search_regs.start diff --git a/src/sysdep.c b/src/sysdep.c index 4bd1f54b9e6..57fff94f552 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -2640,7 +2640,7 @@ system_process_attributes (Lisp_Object pid) ssize_t nread; const char *cmd = NULL; char *cmdline = NULL; - size_t cmdsize = 0, cmdline_size; + ptrdiff_t cmdsize = 0, cmdline_size; unsigned char c; int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount; unsigned long long u_time, s_time, cutime, cstime, start; @@ -2822,8 +2822,10 @@ system_process_attributes (Lisp_Object pid) if (fd >= 0) { char ch; - for (cmdline_size = 0; emacs_read (fd, &ch, 1) == 1; cmdline_size++) + for (cmdline_size = 0; cmdline_size < STRING_BYTES_BOUND; cmdline_size++) { + if (emacs_read (fd, &ch, 1) != 1) + break; c = ch; if (isspace (c) || c == '\\') cmdline_size++; /* for later quoting, see below */ @@ -2844,7 +2846,7 @@ system_process_attributes (Lisp_Object pid) nread = 0; } /* We don't want trailing null characters. */ - for (p = cmdline + nread - 1; p > cmdline && !*p; p--) + for (p = cmdline + nread; p > cmdline + 1 && !p[-1]; p--) nread--; for (p = cmdline; p < cmdline + nread; p++) { diff --git a/src/term.c b/src/term.c index 22056451cb9..bc6fa8f80f9 100644 --- a/src/term.c +++ b/src/term.c @@ -136,10 +136,6 @@ enum no_color_bit static int max_frame_cols; -/* The largest frame height in any call to calculate_costs. */ - -static int max_frame_lines; - /* Non-zero if we have dropped our controlling tty and therefore should not open a frame on stdout. */ static int no_controlling_tty; @@ -497,8 +493,8 @@ tty_clear_end_of_line (struct frame *f, int first_unused_hpos) static unsigned char *encode_terminal_src; static unsigned char *encode_terminal_dst; /* Allocated sizes of the above buffers. */ -static int encode_terminal_src_size; -static int encode_terminal_dst_size; +static ptrdiff_t encode_terminal_src_size; +static ptrdiff_t encode_terminal_dst_size; /* Encode SRC_LEN glyphs starting at SRC to terminal output codes. Set CODING->produced to the byte-length of the resulting byte @@ -509,8 +505,8 @@ encode_terminal_code (struct glyph *src, int src_len, struct coding_system *codi { struct glyph *src_end = src + src_len; unsigned char *buf; - int nchars, nbytes, required; - register int tlen = GLYPH_TABLE_LENGTH; + ptrdiff_t nchars, nbytes, required; + ptrdiff_t tlen = GLYPH_TABLE_LENGTH; register Lisp_Object *tbase = GLYPH_TABLE_BASE; Lisp_Object charset_list; @@ -518,13 +514,13 @@ encode_terminal_code (struct glyph *src, int src_len, struct coding_system *codi multibyte-form. But, it may be enlarged on demand if Vglyph_table contains a string or a composite glyph is encountered. */ - required = MAX_MULTIBYTE_LENGTH * src_len; + if (min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH < src_len) + memory_full (SIZE_MAX); + required = src_len; + required *= MAX_MULTIBYTE_LENGTH; if (encode_terminal_src_size < required) { - if (encode_terminal_src) - encode_terminal_src = xrealloc (encode_terminal_src, required); - else - encode_terminal_src = xmalloc (required); + encode_terminal_src = xrealloc (encode_terminal_src, required); encode_terminal_src_size = required; } @@ -544,19 +540,23 @@ encode_terminal_code (struct glyph *src, int src_len, struct coding_system *codi if (src->u.cmp.automatic) { gstring = composition_gstring_from_id (src->u.cmp.id); - required = src->slice.cmp.to + 1 - src->slice.cmp.from; + required = src->slice.cmp.to - src->slice.cmp.from + 1; } else { cmp = composition_table[src->u.cmp.id]; - required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len; + required = cmp->glyph_len; + required *= MAX_MULTIBYTE_LENGTH; } - if (encode_terminal_src_size < nbytes + required) + if (encode_terminal_src_size - nbytes < required) { - encode_terminal_src_size = nbytes + required; - encode_terminal_src = xrealloc (encode_terminal_src, - encode_terminal_src_size); + ptrdiff_t size; + if (min (PTRDIFF_MAX, SIZE_MAX) - nbytes < required) + memory_full (SIZE_MAX); + size = nbytes + required; + encode_terminal_src = xrealloc (encode_terminal_src, size); + encode_terminal_src_size = size; buf = encode_terminal_src + nbytes; } @@ -627,11 +627,15 @@ encode_terminal_code (struct glyph *src, int src_len, struct coding_system *codi if (NILP (string)) { nbytes = buf - encode_terminal_src; - if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH) + if (encode_terminal_src_size - nbytes < MAX_MULTIBYTE_LENGTH) { - encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH; - encode_terminal_src = xrealloc (encode_terminal_src, - encode_terminal_src_size); + ptrdiff_t size; + if (min (PTRDIFF_MAX, SIZE_MAX) - MAX_MULTIBYTE_LENGTH + < nbytes) + memory_full (SIZE_MAX); + size = nbytes + MAX_MULTIBYTE_LENGTH; + encode_terminal_src = xrealloc (encode_terminal_src, size); + encode_terminal_src_size = size; buf = encode_terminal_src + nbytes; } if (CHAR_BYTE8_P (c) @@ -659,11 +663,14 @@ encode_terminal_code (struct glyph *src, int src_len, struct coding_system *codi if (! STRING_MULTIBYTE (string)) string = string_to_multibyte (string); nbytes = buf - encode_terminal_src; - if (encode_terminal_src_size < nbytes + SBYTES (string)) + if (encode_terminal_src_size - nbytes < SBYTES (string)) { - encode_terminal_src_size = nbytes + SBYTES (string); - encode_terminal_src = xrealloc (encode_terminal_src, - encode_terminal_src_size); + ptrdiff_t size; + if (min (PTRDIFF_MAX, SIZE_MAX) - SBYTES (string) < nbytes) + memory_full (SIZE_MAX); + size = nbytes + SBYTES (string); + encode_terminal_src = xrealloc (encode_terminal_src, size); + encode_terminal_src_size = size; buf = encode_terminal_src + nbytes; } memcpy (buf, SDATA (string), SBYTES (string)); @@ -684,12 +691,9 @@ encode_terminal_code (struct glyph *src, int src_len, struct coding_system *codi coding->source = encode_terminal_src; if (encode_terminal_dst_size == 0) { + encode_terminal_dst = xrealloc (encode_terminal_dst, + encode_terminal_src_size); encode_terminal_dst_size = encode_terminal_src_size; - if (encode_terminal_dst) - encode_terminal_dst = xrealloc (encode_terminal_dst, - encode_terminal_dst_size); - else - encode_terminal_dst = xmalloc (encode_terminal_dst_size); } coding->destination = encode_terminal_dst; coding->dst_bytes = encode_terminal_dst_size; @@ -1156,18 +1160,14 @@ calculate_costs (struct frame *frame) char_ins_del_vector (i.e., char_ins_del_cost) isn't used because X turns off char_ins_del_ok. */ - max_frame_lines = max (max_frame_lines, FRAME_LINES (frame)); max_frame_cols = max (max_frame_cols, FRAME_COLS (frame)); + if ((min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) - 1) / 2 < max_frame_cols) + memory_full (SIZE_MAX); - if (char_ins_del_vector != 0) - char_ins_del_vector - = (int *) xrealloc (char_ins_del_vector, - (sizeof (int) - + 2 * max_frame_cols * sizeof (int))); - else - char_ins_del_vector - = (int *) xmalloc (sizeof (int) - + 2 * max_frame_cols * sizeof (int)); + char_ins_del_vector + = (int *) xrealloc (char_ins_del_vector, + (sizeof (int) + + 2 * max_frame_cols * sizeof (int))); memset (char_ins_del_vector, 0, (sizeof (int) + 2 * max_frame_cols * sizeof (int))); diff --git a/src/termcap.c b/src/termcap.c index 96b9303d62d..791c593c06f 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -480,7 +480,7 @@ tgetent (char *bp, const char *name) /* If BP is malloc'd by us, make sure it is big enough. */ if (malloc_size) { - int offset1 = bp1 - bp, offset2 = tc_search_point - bp; + ptrdiff_t offset1 = bp1 - bp, offset2 = tc_search_point - bp; malloc_size = offset1 + buf.size; bp = termcap_name = (char *) xrealloc (bp, malloc_size); bp1 = termcap_name + offset1; @@ -619,7 +619,6 @@ gobble_line (int fd, register struct termcap_buffer *bufp, char *append_end) register char *end; register int nread; register char *buf = bufp->beg; - register char *tem; if (!append_end) append_end = bufp->ptr; @@ -636,14 +635,17 @@ gobble_line (int fd, register struct termcap_buffer *bufp, char *append_end) { if (bufp->full == bufp->size) { - if ((PTRDIFF_MAX - 1) / 2 < bufp->size) + ptrdiff_t ptr_offset = bufp->ptr - buf; + ptrdiff_t append_end_offset = append_end - buf; + ptrdiff_t size; + if ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / 2 < bufp->size) memory_full (SIZE_MAX); - bufp->size *= 2; + size = 2 * bufp->size; /* Add 1 to size to ensure room for terminating null. */ - tem = (char *) xrealloc (buf, bufp->size + 1); - bufp->ptr = (bufp->ptr - buf) + tem; - append_end = (append_end - buf) + tem; - bufp->beg = buf = tem; + bufp->beg = buf = (char *) xrealloc (buf, size + 1); + bufp->size = size; + bufp->ptr = buf + ptr_offset; + append_end = buf + append_end_offset; } } else diff --git a/src/termhooks.h b/src/termhooks.h index 6a58517a85a..63d166b6418 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -288,12 +288,12 @@ enum { /* The next four modifier bits are used also in keyboard events at the Lisp level. - It's probably not the greatest idea to use the 2^23 bit for any + It's probably not the greatest idea to use the 2^28 bit for any modifier. It may or may not be the sign bit, depending on - VALBITS, so using it to represent a modifier key means that + FIXNUM_BITS, so using it to represent a modifier key means that characters thus modified have different integer equivalents depending on the architecture they're running on. Oh, and - applying XINT to a character whose 2^23 bit is set sign-extends + applying XINT to a character whose 2^28 bit is set might sign-extend it, so you get a bunch of bits in the mask you didn't want. The CHAR_ macros are defined in lisp.h. */ diff --git a/src/tparam.c b/src/tparam.c index ed28cd7397f..06cec873153 100644 --- a/src/tparam.c +++ b/src/tparam.c @@ -79,33 +79,38 @@ tparam1 (const char *string, char *outstring, int len, register const char *p = string; register char *op = outstring; char *outend; - int outlen = 0; + char *new = 0; + ptrdiff_t outlen = 0; register int tem; int *old_argp = argp; /* can move */ int *fixed_argp = argp; /* never moves */ int explicit_param_p = 0; /* set by %p */ - int doleft = 0; - int doup = 0; + ptrdiff_t doleft = 0; + ptrdiff_t doup = 0; + ptrdiff_t append_len = 0; outend = outstring + len; while (1) { /* If the buffer might be too short, make it bigger. */ - if (op + 5 >= outend) + while (outend - op - append_len <= 5) { - register char *new; - int offset = op - outstring; + ptrdiff_t offset = op - outstring; if (outlen == 0) { + if (min (PTRDIFF_MAX, SIZE_MAX) - 40 < len) + goto out_of_memory; outlen = len + 40; new = (char *) xmalloc (outlen); memcpy (new, outstring, offset); } else { + if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < outlen) + goto out_of_memory; outlen *= 2; new = (char *) xrealloc (outstring, outlen); } @@ -167,11 +172,19 @@ tparam1 (const char *string, char *outstring, int len, and this is one of them, increment it. */ while (tem == 0 || tem == '\n' || tem == '\t') { + ptrdiff_t append_len_incr; tem++; if (argp == old_argp) - doup++, outend -= strlen (up); + doup++, append_len_incr = strlen (up); else - doleft++, outend -= strlen (left); + doleft++, append_len_incr = strlen (left); + if (PTRDIFF_MAX - append_len < append_len_incr) + { + out_of_memory: + xfree (new); + memory_full (SIZE_MAX); + } + append_len += append_len_incr; } } *op++ = tem ? tem : 0200; diff --git a/src/window.c b/src/window.c index 3f5a743f5c6..04fea6b9bf6 100644 --- a/src/window.c +++ b/src/window.c @@ -5069,7 +5069,7 @@ and redisplay normally--don't erase and redraw the frame. */) && (!EQ (Vrecenter_redisplay, Qtty) || !NILP (Ftty_type (selected_frame)))) { - int i; + ptrdiff_t i; /* Invalidate pixel data calculated for all compositions. */ for (i = 0; i < n_compositions; i++) diff --git a/src/xdisp.c b/src/xdisp.c index 84c75bd91d9..d44e677eeb7 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2478,10 +2478,7 @@ init_iterator (struct it *it, struct window *w, else if (INTEGERP (w->redisplay_end_trigger)) it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger); - /* Correct bogus values of tab_width. */ - it->tab_width = XINT (BVAR (current_buffer, tab_width)); - if (it->tab_width <= 0 || it->tab_width > 1000) - it->tab_width = 8; + it->tab_width = SANE_TAB_WIDTH (current_buffer); /* Are lines in the display truncated? */ if (base_face_id != DEFAULT_FACE_ID @@ -10390,8 +10387,12 @@ store_mode_line_noprop_char (char c) double the buffer's size. */ if (mode_line_noprop_ptr == mode_line_noprop_buf_end) { - int len = MODE_LINE_NOPROP_LEN (0); - int new_size = 2 * len * sizeof *mode_line_noprop_buf; + ptrdiff_t len = MODE_LINE_NOPROP_LEN (0); + ptrdiff_t new_size; + + if (STRING_BYTES_BOUND / 2 < len) + memory_full (SIZE_MAX); + new_size = 2 * len; mode_line_noprop_buf = (char *) xrealloc (mode_line_noprop_buf, new_size); mode_line_noprop_buf_end = mode_line_noprop_buf + new_size; mode_line_noprop_ptr = mode_line_noprop_buf + len; @@ -10455,9 +10456,9 @@ x_consider_frame_title (Lisp_Object frame) /* Do we have more than one visible frame on this X display? */ Lisp_Object tail; Lisp_Object fmt; - int title_start; + ptrdiff_t title_start; char *title; - int len; + ptrdiff_t len; struct it it; int count = SPECPDL_INDEX (); @@ -21268,7 +21269,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, if (FRAME_WINDOW_P (it->f) && valid_image_p (prop)) { - int id = lookup_image (it->f, prop); + ptrdiff_t id = lookup_image (it->f, prop); struct image *img = IMAGE_FROM_ID (it->f, id); return OK_PIXELS (width_p ? img->width : img->height); @@ -22140,7 +22141,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) do { \ int face_id = (row)->glyphs[area][START].face_id; \ struct face *base_face = FACE_FROM_ID (f, face_id); \ - int cmp_id = (row)->glyphs[area][START].u.cmp.id; \ + ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \ struct composition *cmp = composition_table[cmp_id]; \ XChar2b *char2b; \ struct glyph_string *first_s IF_LINT (= NULL); \ diff --git a/src/xfaces.c b/src/xfaces.c index 52b125b42e6..352fdb4b082 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -2668,8 +2668,13 @@ Value is a vector of face attributes. */) property `face' of the Lisp face name. */ if (next_lface_id == lface_id_to_name_size) { - int new_size = max (50, 2 * lface_id_to_name_size); - int sz = new_size * sizeof *lface_id_to_name; + ptrdiff_t new_size, sz; + if (min (min (PTRDIFF_MAX, SIZE_MAX) / 2 / sizeof *lface_id_to_name, + MOST_POSITIVE_FIXNUM) + < lface_id_to_name_size) + memory_full (SIZE_MAX); + new_size = max (50, 2 * lface_id_to_name_size); + sz = new_size * sizeof *lface_id_to_name; lface_id_to_name = (Lisp_Object *) xrealloc (lface_id_to_name, sz); lface_id_to_name_size = new_size; } @@ -4412,7 +4417,10 @@ cache_face (struct face_cache *c, struct face *face, unsigned int hash) if (c->used == c->size) { int new_size, sz; - new_size = min (2 * c->size, MAX_FACE_ID); + new_size = + min (2 * c->size, + min (MAX_FACE_ID, + min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->faces_by_id)); if (new_size == c->size) abort (); /* Alternatives? ++kfs */ sz = new_size * sizeof *c->faces_by_id; diff --git a/src/xfns.c b/src/xfns.c index eec19b9d275..1169acb3cf5 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -145,7 +145,8 @@ static Lisp_Object Qcompound_text, Qcancel_timer; Lisp_Object Qfont_param; #if GLYPH_DEBUG -static int image_cache_refcount, dpyinfo_refcount; +static ptrdiff_t image_cache_refcount; +static int dpyinfo_refcount; #endif #if defined (USE_GTK) && defined (HAVE_FREETYPE) @@ -1470,7 +1471,8 @@ x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object old the result should be `COMPOUND_TEXT'. */ static unsigned char * -x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp, int *text_bytes, int *stringp, int *freep) +x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp, + ptrdiff_t *text_bytes, int *stringp, int *freep) { int result = string_xstring_p (string); struct coding_system coding; @@ -1488,6 +1490,8 @@ x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp, in coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK); /* We suppress producing escape sequences for composition. */ coding.common_flags &= ~CODING_ANNOTATION_MASK; + if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < SCHARS (string)) + memory_full (SIZE_MAX); coding.dst_bytes = SCHARS (string) * 2; coding.destination = (unsigned char *) xmalloc (coding.dst_bytes); encode_coding_object (&coding, string, 0, 0, @@ -1511,7 +1515,8 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name) BLOCK_INPUT; { XTextProperty text, icon; - int bytes, stringp; + ptrdiff_t bytes; + int stringp; int do_free_icon_value = 0, do_free_text_value = 0; Lisp_Object coding_system; Lisp_Object encoded_name; @@ -1550,6 +1555,8 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name) : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); text.format = 8; text.nitems = bytes; + if (text.nitems != bytes) + error ("Window name too large"); if (!STRINGP (f->icon_name)) { @@ -1565,6 +1572,8 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name) : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); icon.format = 8; icon.nitems = bytes; + if (icon.nitems != bytes) + error ("Icon name too large"); encoded_icon_name = ENCODE_UTF_8 (f->icon_name); } @@ -4193,21 +4202,21 @@ FRAME. Default is to change on the edit X window. */) if (CONSP (value)) { + ptrdiff_t elsize; + nelements = x_check_property_data (value); if (nelements == -1) error ("Bad data in VALUE, must be number, string or cons"); - if (element_format == 8) - data = (unsigned char *) xmalloc (nelements); - else if (element_format == 16) - data = (unsigned char *) xmalloc (nelements*2); - else /* format == 32 */ - /* The man page for XChangeProperty: - "If the specified format is 32, the property data must be a - long array." - This applies even if long is more than 64 bits. The X library - converts to 32 bits before sending to the X server. */ - data = (unsigned char *) xmalloc (nelements * sizeof(long)); + /* The man page for XChangeProperty: + "If the specified format is 32, the property data must be a + long array." + This applies even if long is more than 32 bits. The X library + converts to 32 bits before sending to the X server. */ + elsize = element_format == 32 ? sizeof (long) : element_format >> 3; + if (min (PTRDIFF_MAX, SIZE_MAX) / elsize < nelements) + memory_full (SIZE_MAX); + data = (unsigned char *) xmalloc (nelements * elsize); x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format); } @@ -4215,7 +4224,9 @@ FRAME. Default is to change on the edit X window. */) { CHECK_STRING (value); data = SDATA (value); - nelements = SCHARS (value); + if (INT_MAX < SBYTES (value)) + error ("VALUE too long"); + nelements = SBYTES (value); } BLOCK_INPUT; diff --git a/src/xgselect.c b/src/xgselect.c index 9ccdd37489f..d1844610077 100644 --- a/src/xgselect.c +++ b/src/xgselect.c @@ -54,10 +54,16 @@ xg_select (int max_fds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, do { if (n_gfds > gfds_size) { - while (n_gfds > gfds_size) - gfds_size *= 2; + int gfds_size_max = + min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX) / sizeof *gfds); + int size; + if (gfds_size_max / 2 < n_gfds) + memory_full (SIZE_MAX); + size = 2 * n_gfds; + gfds_size = 0; xfree (gfds); - gfds = xmalloc (sizeof (*gfds) * gfds_size); + gfds = xmalloc (sizeof *gfds * size); + gfds_size = size; } n_gfds = g_main_context_query (context, diff --git a/src/xrdb.c b/src/xrdb.c index 6a16e3260bd..7c2cd586b09 100644 --- a/src/xrdb.c +++ b/src/xrdb.c @@ -204,7 +204,10 @@ magic_file_p (const char *string, EMACS_INT string_len, const char *class, if (path_size - path_len <= next_len) { if (min (PTRDIFF_MAX, SIZE_MAX) / 2 - 1 - path_len < next_len) - memory_full (SIZE_MAX); + { + xfree (path); + memory_full (SIZE_MAX); + } path_size = (path_len + next_len + 1) * 2; path = (char *) xrealloc (path, path_size); } @@ -426,24 +429,22 @@ get_environ_db (void) { XrmDatabase db; char *p; - char *path = 0, *home = 0; - const char *host; + char *path = 0; if ((p = getenv ("XENVIRONMENT")) == NULL) { - home = gethomedir (); - host = get_system_name (); - path = (char *) xmalloc (strlen (home) - + sizeof (".Xdefaults-") - + strlen (host)); - sprintf (path, "%s%s%s", home, ".Xdefaults-", host); + static char const xdefaults[] = ".Xdefaults-"; + char *home = gethomedir (); + char const *host = get_system_name (); + ptrdiff_t pathsize = strlen (home) + sizeof xdefaults + strlen (host); + path = (char *) xrealloc (home, pathsize); + strcat (strcat (path, xdefaults), host); p = path; } db = XrmGetFileDatabase (p); xfree (path); - xfree (home); return db; } diff --git a/src/xselect.c b/src/xselect.c index f63977a73de..d8b7b077a8c 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -66,22 +66,15 @@ static Lisp_Object wait_for_property_change_unwind (Lisp_Object); static void wait_for_property_change (struct prop_location *); static Lisp_Object x_get_foreign_selection (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); -static void x_get_window_property (Display *, Window, Atom, - unsigned char **, int *, - Atom *, int *, unsigned long *, int); -static void receive_incremental_selection (Display *, Window, Atom, - Lisp_Object, unsigned, - unsigned char **, int *, - Atom *, int *, unsigned long *); static Lisp_Object x_get_window_property_as_lisp_data (Display *, Window, Atom, Lisp_Object, Atom); static Lisp_Object selection_data_to_lisp_data (Display *, const unsigned char *, - int, Atom, int); + ptrdiff_t, Atom, int); static void lisp_data_to_selection_data (Display *, Lisp_Object, unsigned char **, Atom *, - unsigned *, int *, int *); + ptrdiff_t *, int *, int *); static Lisp_Object clean_local_selection_data (Lisp_Object); /* Printing traces to stderr. */ @@ -114,15 +107,37 @@ static Lisp_Object Qcompound_text_with_extensions; static Lisp_Object Qforeign_selection; static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions; +/* Bytes needed to represent 'long' data. This is as per libX11; it + is not necessarily sizeof (long). */ +#define X_LONG_SIZE 4 + +/* Maximum unsigned 'short' and 'long' values suitable for libX11. */ +#define X_USHRT_MAX 0xffff +#define X_ULONG_MAX 0xffffffff + /* If this is a smaller number than the max-request-size of the display, emacs will use INCR selection transfer when the selection is larger than this. The max-request-size is usually around 64k, so if you want emacs to use incremental selection transfers when the selection is smaller than that, set this. I added this mostly for debugging the - incremental transfer stuff, but it might improve server performance. */ -#define MAX_SELECTION_QUANTUM 0xFFFFFF + incremental transfer stuff, but it might improve server performance. + + This value cannot exceed INT_MAX / max (X_LONG_SIZE, sizeof (long)) + because it is multiplied by X_LONG_SIZE and by sizeof (long) in + subscript calculations. Similarly for PTRDIFF_MAX - 1 or SIZE_MAX + - 1 in place of INT_MAX. */ +#define MAX_SELECTION_QUANTUM \ + ((int) min (0xFFFFFF, (min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX) - 1) \ + / max (X_LONG_SIZE, sizeof (long))))) -#define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100) +static int +selection_quantum (Display *display) +{ + long mrs = XMaxRequestSize (display); + return (mrs < MAX_SELECTION_QUANTUM / X_LONG_SIZE + 25 + ? (mrs - 25) * X_LONG_SIZE + : MAX_SELECTION_QUANTUM); +} #define LOCAL_SELECTION(selection_symbol,dpyinfo) \ assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) @@ -477,7 +492,7 @@ static struct x_display_info *selection_request_dpyinfo; struct selection_data { unsigned char *data; - unsigned int size; + ptrdiff_t size; int format; Atom type; int nofree; @@ -581,14 +596,11 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy XSelectionEvent *reply = &(reply_base.xselection); Display *display = SELECTION_EVENT_DISPLAY (event); Window window = SELECTION_EVENT_REQUESTOR (event); - int bytes_remaining; - int max_bytes = SELECTION_QUANTUM (display); + ptrdiff_t bytes_remaining; + int max_bytes = selection_quantum (display); int count = SPECPDL_INDEX (); struct selection_data *cs; - if (max_bytes > MAX_SELECTION_QUANTUM) - max_bytes = MAX_SELECTION_QUANTUM; - reply->type = SelectionNotify; reply->display = display; reply->requestor = window; @@ -616,11 +628,12 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy if (cs->property == None) continue; - bytes_remaining = cs->size * (cs->format / 8); + bytes_remaining = cs->size; + bytes_remaining *= cs->format >> 3; if (bytes_remaining <= max_bytes) { /* Send all the data at once, with minimal handshaking. */ - TRACE1 ("Sending all %d bytes", bytes_remaining); + TRACE1 ("Sending all %"pD"d bytes", bytes_remaining); XChangeProperty (display, window, cs->property, cs->type, cs->format, PropModeReplace, cs->data, cs->size); @@ -628,9 +641,9 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy else { /* Send an INCR tag to initiate incremental transfer. */ - long value[1]; + unsigned long value[1]; - TRACE2 ("Start sending %d bytes incrementally (%s)", + TRACE2 ("Start sending %"pD"d bytes incrementally (%s)", bytes_remaining, XGetAtomName (display, cs->property)); cs->wait_object = expect_property_change (display, window, cs->property, @@ -638,7 +651,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy /* XChangeProperty expects an array of long even if long is more than 32 bits. */ - value[0] = bytes_remaining; + value[0] = min (bytes_remaining, X_ULONG_MAX); XChangeProperty (display, window, cs->property, dpyinfo->Xatom_INCR, 32, PropModeReplace, (unsigned char *) value, 1); @@ -672,7 +685,8 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy int had_errors = x_had_errors_p (display); UNBLOCK_INPUT; - bytes_remaining = cs->size * format_bytes; + bytes_remaining = cs->size; + bytes_remaining *= format_bytes; /* Wait for the requester to ack by deleting the property. This can run Lisp code (process handlers) or signal. */ @@ -810,7 +824,7 @@ x_handle_selection_request (struct input_event *event) non-None property. */ Window requestor = SELECTION_EVENT_REQUESTOR (event); Lisp_Object multprop; - int j, nselections; + ptrdiff_t j, nselections; if (property == None) goto DONE; multprop @@ -1269,19 +1283,28 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, static void x_get_window_property (Display *display, Window window, Atom property, - unsigned char **data_ret, int *bytes_ret, + unsigned char **data_ret, ptrdiff_t *bytes_ret, Atom *actual_type_ret, int *actual_format_ret, unsigned long *actual_size_ret, int delete_p) { - int total_size; + ptrdiff_t total_size; unsigned long bytes_remaining; - int offset = 0; + ptrdiff_t offset = 0; + unsigned char *data = 0; unsigned char *tmp_data = 0; int result; - int buffer_size = SELECTION_QUANTUM (display); + int buffer_size = selection_quantum (display); + + /* Wide enough to avoid overflow in expressions using it. */ + ptrdiff_t x_long_size = X_LONG_SIZE; - if (buffer_size > MAX_SELECTION_QUANTUM) - buffer_size = MAX_SELECTION_QUANTUM; + /* Maximum value for TOTAL_SIZE. It cannot exceed PTRDIFF_MAX - 1 + and SIZE_MAX - 1, for an extra byte at the end. And it cannot + exceed LONG_MAX * X_LONG_SIZE, for XGetWindowProperty. */ + ptrdiff_t total_size_max = + ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / x_long_size < LONG_MAX + ? min (PTRDIFF_MAX, SIZE_MAX) - 1 + : LONG_MAX * x_long_size); BLOCK_INPUT; @@ -1292,49 +1315,44 @@ x_get_window_property (Display *display, Window window, Atom property, actual_size_ret, &bytes_remaining, &tmp_data); if (result != Success) - { - UNBLOCK_INPUT; - *data_ret = 0; - *bytes_ret = 0; - return; - } + goto done; /* This was allocated by Xlib, so use XFree. */ XFree ((char *) tmp_data); if (*actual_type_ret == None || *actual_format_ret == 0) - { - UNBLOCK_INPUT; - return; - } + goto done; - total_size = bytes_remaining + 1; - *data_ret = (unsigned char *) xmalloc (total_size); + if (total_size_max < bytes_remaining) + goto size_overflow; + total_size = bytes_remaining; + data = malloc (total_size + 1); + if (! data) + goto memory_exhausted; /* Now read, until we've gotten it all. */ while (bytes_remaining) { -#ifdef TRACE_SELECTION - unsigned long last = bytes_remaining; -#endif + ptrdiff_t bytes_gotten; + int bytes_per_item; result = XGetWindowProperty (display, window, property, - (long)offset/4, (long)buffer_size/4, + offset / X_LONG_SIZE, + buffer_size / X_LONG_SIZE, False, AnyPropertyType, actual_type_ret, actual_format_ret, actual_size_ret, &bytes_remaining, &tmp_data); - TRACE2 ("Read %lu bytes from property %s", - last - bytes_remaining, - XGetAtomName (display, property)); - /* If this doesn't return Success at this point, it means that some clod deleted the selection while we were in the midst of reading it. Deal with that, I guess.... */ if (result != Success) break; + bytes_per_item = *actual_format_ret >> 3; + xassert (*actual_size_ret <= buffer_size / bytes_per_item); + /* The man page for XGetWindowProperty says: "If the returned format is 32, the returned data is represented as a long array and should be cast to that type to obtain the @@ -1348,32 +1366,61 @@ x_get_window_property (Display *display, Window window, Atom property, The bytes and offsets passed to XGetWindowProperty refers to the property and those are indeed in 32 bit quantities if format is 32. */ + bytes_gotten = *actual_size_ret; + bytes_gotten *= bytes_per_item; + + TRACE2 ("Read %"pD"d bytes from property %s", + bytes_gotten, XGetAtomName (display, property)); + + if (total_size - offset < bytes_gotten) + { + unsigned char *data1; + ptrdiff_t remaining_lim = total_size_max - offset - bytes_gotten; + if (remaining_lim < 0 || remaining_lim < bytes_remaining) + goto size_overflow; + total_size = offset + bytes_gotten + bytes_remaining; + data1 = realloc (data, total_size + 1); + if (! data1) + goto memory_exhausted; + data = data1; + } + if (32 < BITS_PER_LONG && *actual_format_ret == 32) { unsigned long i; - int *idata = (int *) ((*data_ret) + offset); + int *idata = (int *) (data + offset); long *ldata = (long *) tmp_data; for (i = 0; i < *actual_size_ret; ++i) - { - idata[i]= (int) ldata[i]; - offset += 4; - } + idata[i] = ldata[i]; } else - { - *actual_size_ret *= *actual_format_ret / 8; - memcpy ((*data_ret) + offset, tmp_data, *actual_size_ret); - offset += *actual_size_ret; - } + memcpy (data + offset, tmp_data, bytes_gotten); + + offset += bytes_gotten; /* This was allocated by Xlib, so use XFree. */ XFree ((char *) tmp_data); } XFlush (display); + data[offset] = '\0'; + + done: UNBLOCK_INPUT; + *data_ret = data; *bytes_ret = offset; + return; + + size_overflow: + free (data); + UNBLOCK_INPUT; + memory_full (SIZE_MAX); + + memory_exhausted: + free (data); + UNBLOCK_INPUT; + memory_full (total_size + 1); } /* Use xfree, not XFree, to free the data obtained with this function. */ @@ -1382,16 +1429,19 @@ static void receive_incremental_selection (Display *display, Window window, Atom property, Lisp_Object target_type, unsigned int min_size_bytes, - unsigned char **data_ret, int *size_bytes_ret, + unsigned char **data_ret, + ptrdiff_t *size_bytes_ret, Atom *type_ret, int *format_ret, unsigned long *size_ret) { - int offset = 0; + ptrdiff_t offset = 0; struct prop_location *wait_object; + if (min (PTRDIFF_MAX, SIZE_MAX) < min_size_bytes) + memory_full (SIZE_MAX); + *data_ret = (unsigned char *) xmalloc (min_size_bytes); *size_bytes_ret = min_size_bytes; - *data_ret = (unsigned char *) xmalloc (*size_bytes_ret); - TRACE1 ("Read %d bytes incrementally", min_size_bytes); + TRACE1 ("Read %u bytes incrementally", min_size_bytes); /* At this point, we have read an INCR property. Delete the property to ack it. @@ -1416,7 +1466,7 @@ receive_incremental_selection (Display *display, Window window, Atom property, while (1) { unsigned char *tmp_data; - int tmp_size_bytes; + ptrdiff_t tmp_size_bytes; TRACE0 (" Wait for property change"); wait_for_property_change (wait_object); @@ -1429,7 +1479,7 @@ receive_incremental_selection (Display *display, Window window, Atom property, &tmp_data, &tmp_size_bytes, type_ret, format_ret, size_ret, 1); - TRACE1 (" Read increment of %d bytes", tmp_size_bytes); + TRACE1 (" Read increment of %"pD"d bytes", tmp_size_bytes); if (tmp_size_bytes == 0) /* we're done */ { @@ -1452,10 +1502,17 @@ receive_incremental_selection (Display *display, Window window, Atom property, XFlush (display); UNBLOCK_INPUT; - if (*size_bytes_ret < offset + tmp_size_bytes) + if (*size_bytes_ret - offset < tmp_size_bytes) { - *size_bytes_ret = offset + tmp_size_bytes; - *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret); + ptrdiff_t size; + if (min (PTRDIFF_MAX, SIZE_MAX) - offset < tmp_size_bytes) + { + xfree (tmp_data); + memory_full (SIZE_MAX); + } + size = offset + tmp_size_bytes; + *data_ret = (unsigned char *) xrealloc (*data_ret, size); + *size_bytes_ret = size; } memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes); @@ -1482,7 +1539,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, int actual_format; unsigned long actual_size; unsigned char *data = 0; - int bytes = 0; + ptrdiff_t bytes = 0; Lisp_Object val; struct x_display_info *dpyinfo = x_display_info_for_display (display); @@ -1574,7 +1631,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, static Lisp_Object selection_data_to_lisp_data (Display *display, const unsigned char *data, - int size, Atom type, int format) + ptrdiff_t size, Atom type, int format) { struct x_display_info *dpyinfo = x_display_info_for_display (display); @@ -1607,7 +1664,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data, /* Treat ATOM_PAIR type similar to list of atoms. */ || type == dpyinfo->Xatom_ATOM_PAIR) { - int i; + ptrdiff_t i; /* On a 64 bit machine sizeof(Atom) == sizeof(long) == 8. But the callers of these function has made sure the data for format == 32 is an array of int. Thus, use int instead @@ -1634,28 +1691,29 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data, else if (format == 32 && size == sizeof (int)) return INTEGER_TO_CONS (((unsigned int *) data) [0]); else if (format == 16 && size == sizeof (short)) - return make_number ((int) (((unsigned short *) data) [0])); + return make_number (((unsigned short *) data) [0]); /* Convert any other kind of data to a vector of numbers, represented as above (as an integer, or a cons of two 16 bit integers.) */ else if (format == 16) { - int i; + ptrdiff_t i; Lisp_Object v; v = Fmake_vector (make_number (size / 2), make_number (0)); for (i = 0; i < size / 2; i++) { - int j = (int) ((unsigned short *) data) [i]; + EMACS_INT j = ((unsigned short *) data) [i]; Faset (v, make_number (i), make_number (j)); } return v; } else { - int i; - Lisp_Object v = Fmake_vector (make_number (size / 4), make_number (0)); - for (i = 0; i < size / 4; i++) + ptrdiff_t i; + Lisp_Object v = Fmake_vector (make_number (size / X_LONG_SIZE), + make_number (0)); + for (i = 0; i < size / X_LONG_SIZE; i++) { unsigned int j = ((unsigned int *) data) [i]; Faset (v, make_number (i), INTEGER_TO_CONS (j)); @@ -1670,7 +1728,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data, static void lisp_data_to_selection_data (Display *display, Lisp_Object obj, unsigned char **data_ret, Atom *type_ret, - unsigned int *size_ret, + ptrdiff_t *size_ret, int *format_ret, int *nofree_ret) { Lisp_Object type = Qnil; @@ -1707,22 +1765,20 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, } else if (SYMBOLP (obj)) { + *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1); *format_ret = 32; *size_ret = 1; - *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1); (*data_ret) [sizeof (Atom)] = 0; (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj); if (NILP (type)) type = QATOM; } - else if (INTEGERP (obj) - && XINT (obj) < 0xFFFF - && XINT (obj) > -0xFFFF) + else if (RANGED_INTEGERP (0, obj, X_USHRT_MAX)) { + *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1); *format_ret = 16; *size_ret = 1; - *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1); (*data_ret) [sizeof (short)] = 0; - (*(short **) data_ret) [0] = (short) XINT (obj); + (*(unsigned short **) data_ret) [0] = XINT (obj); if (NILP (type)) type = QINTEGER; } else if (INTEGERP (obj) @@ -1731,11 +1787,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, || (CONSP (XCDR (obj)) && INTEGERP (XCAR (XCDR (obj))))))) { + *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1); *format_ret = 32; *size_ret = 1; - *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1); (*data_ret) [sizeof (long)] = 0; - (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, ULONG_MAX); + (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, X_ULONG_MAX); if (NILP (type)) type = QINTEGER; } else if (VECTORP (obj)) @@ -1744,50 +1800,54 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, a set of 16 or 32 bit INTEGERs; or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...] */ - int i; + ptrdiff_t i; + ptrdiff_t size = ASIZE (obj); if (SYMBOLP (XVECTOR (obj)->contents [0])) /* This vector is an ATOM set */ { + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Atom) < size) + memory_full (SIZE_MAX); if (NILP (type)) type = QATOM; - *size_ret = ASIZE (obj); - *format_ret = 32; - for (i = 0; i < *size_ret; i++) + for (i = 0; i < size; i++) if (!SYMBOLP (XVECTOR (obj)->contents [i])) signal_error ("All elements of selection vector must have same type", obj); - *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom)); - for (i = 0; i < *size_ret; i++) + *data_ret = (unsigned char *) xmalloc (size * sizeof (Atom)); + *format_ret = 32; + *size_ret = size; + for (i = 0; i < size; i++) (*(Atom **) data_ret) [i] = symbol_to_x_atom (dpyinfo, XVECTOR (obj)->contents [i]); } else /* This vector is an INTEGER set, or something like it */ { + int format = 16; int data_size = 2; - *size_ret = ASIZE (obj); if (NILP (type)) type = QINTEGER; - *format_ret = 16; - for (i = 0; i < *size_ret; i++) - if (CONSP (XVECTOR (obj)->contents [i])) - *format_ret = 32; - else if (!INTEGERP (XVECTOR (obj)->contents [i])) - signal_error (/* Qselection_error */ - "Elements of selection vector must be integers or conses of integers", - obj); - - /* Use sizeof(long) even if it is more than 32 bits. See comment - in x_get_window_property and x_fill_property_data. */ - - if (*format_ret == 32) data_size = sizeof(long); - *data_ret = (unsigned char *) xmalloc (*size_ret * data_size); - for (i = 0; i < *size_ret; i++) - if (*format_ret == 32) + for (i = 0; i < size; i++) + if (X_USHRT_MAX + < cons_to_unsigned (XVECTOR (obj)->contents[i], X_ULONG_MAX)) + { + /* Use sizeof (long) even if it is more than 32 bits. + See comment in x_get_window_property and + x_fill_property_data. */ + data_size = sizeof (long); + format = 32; + } + if (min (PTRDIFF_MAX, SIZE_MAX) / data_size < size) + memory_full (SIZE_MAX); + *data_ret = (unsigned char *) xmalloc (size * data_size); + *format_ret = format; + *size_ret = size; + for (i = 0; i < size; i++) + if (format == 32) (*((unsigned long **) data_ret)) [i] = - cons_to_unsigned (XVECTOR (obj)->contents [i], ULONG_MAX); + cons_to_unsigned (XVECTOR (obj)->contents[i], X_ULONG_MAX); else (*((unsigned short **) data_ret)) [i] = - cons_to_unsigned (XVECTOR (obj)->contents [i], USHRT_MAX); + cons_to_unsigned (XVECTOR (obj)->contents[i], X_USHRT_MAX); } } else @@ -1817,8 +1877,8 @@ clean_local_selection_data (Lisp_Object obj) } if (VECTORP (obj)) { - int i; - int size = ASIZE (obj); + ptrdiff_t i; + ptrdiff_t size = ASIZE (obj); Lisp_Object copy; if (size == 1) return clean_local_selection_data (XVECTOR (obj)->contents [0]); @@ -2213,6 +2273,8 @@ x_check_property_data (Lisp_Object data) else if (CONSP (o) && (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o)))) return -1; + if (size == INT_MAX) + return -1; size++; } @@ -2294,8 +2356,11 @@ Lisp_Object x_property_data_to_lisp (struct frame *f, const unsigned char *data, Atom type, int format, long unsigned int size) { + ptrdiff_t format_bytes = format >> 3; + if (PTRDIFF_MAX / format_bytes < size) + memory_full (SIZE_MAX); return selection_data_to_lisp_data (FRAME_X_DISPLAY (f), - data, size*format/8, type, format); + data, size * format_bytes, type, format); } /* Get the mouse position in frame relative coordinates. */ @@ -2405,10 +2470,10 @@ FRAME is on. If FRAME is nil, the selected frame is used. */) if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *dpyinfo->x_dnd_atoms / 2 < dpyinfo->x_dnd_atoms_size) memory_full (SIZE_MAX); - dpyinfo->x_dnd_atoms_size *= 2; dpyinfo->x_dnd_atoms = xrealloc (dpyinfo->x_dnd_atoms, - sizeof (*dpyinfo->x_dnd_atoms) - * dpyinfo->x_dnd_atoms_size); + (2 * sizeof *dpyinfo->x_dnd_atoms + * dpyinfo->x_dnd_atoms_size)); + dpyinfo->x_dnd_atoms_size *= 2; } dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom; @@ -2426,7 +2491,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_disp unsigned long size = 160/event->format; int x, y; unsigned char *data = (unsigned char *) event->data.b; - int idata[5]; + unsigned int idata[5]; ptrdiff_t i; for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) @@ -2444,7 +2509,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_disp if (32 < BITS_PER_LONG && event->format == 32) { for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */ - idata[i] = (int) event->data.l[i]; + idata[i] = event->data.l[i]; data = (unsigned char *) idata; } diff --git a/src/xsmfns.c b/src/xsmfns.c index cb56ae648d1..217087dbae7 100644 --- a/src/xsmfns.c +++ b/src/xsmfns.c @@ -223,6 +223,9 @@ smc_save_yourself_CB (SmcConn smcConn, props[props_idx]->name = xstrdup (SmRestartCommand); props[props_idx]->type = xstrdup (SmLISTofARRAY8); /* /path/to/emacs, --smid=xxx --no-splash --chdir=dir ... */ + if (min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX) / sizeof *vp) - 3 + < initial_argc) + memory_full (SIZE_MAX); i = 3 + initial_argc; props[props_idx]->num_vals = i; vp = (SmPropValue *) xmalloc (i * sizeof(*vp)); diff --git a/src/xterm.c b/src/xterm.c index 20516ee9d6f..4ef0061dba6 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1625,19 +1625,21 @@ x_color_cells (Display *dpy, int *ncells) if (dpyinfo->color_cells == NULL) { Screen *screen = dpyinfo->screen; + int ncolor_cells = XDisplayCells (dpy, XScreenNumberOfScreen (screen)); int i; - dpyinfo->ncolor_cells - = XDisplayCells (dpy, XScreenNumberOfScreen (screen)); + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (XColor) < ncolor_cells) + memory_full (SIZE_MAX); dpyinfo->color_cells - = (XColor *) xmalloc (dpyinfo->ncolor_cells + = (XColor *) xmalloc (ncolor_cells * sizeof *dpyinfo->color_cells); + dpyinfo->ncolor_cells = ncolor_cells; - for (i = 0; i < dpyinfo->ncolor_cells; ++i) + for (i = 0; i < ncolor_cells; ++i) dpyinfo->color_cells[i].pixel = i; XQueryColors (dpy, dpyinfo->cmap, - dpyinfo->color_cells, dpyinfo->ncolor_cells); + dpyinfo->color_cells, ncolor_cells); } *ncells = dpyinfo->ncolor_cells; @@ -4190,7 +4192,7 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name, x_send_scroll_bar_event and x_scroll_bar_to_input_event. */ static struct window **scroll_bar_windows; -static size_t scroll_bar_windows_size; +static ptrdiff_t scroll_bar_windows_size; /* Send a client message with message type Xatom_Scrollbar for a @@ -4205,7 +4207,7 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole) XClientMessageEvent *ev = (XClientMessageEvent *) &event; struct window *w = XWINDOW (window); struct frame *f = XFRAME (w->frame); - size_t i; + ptrdiff_t i; BLOCK_INPUT; @@ -4226,12 +4228,16 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole) if (i == scroll_bar_windows_size) { - size_t new_size = max (10, 2 * scroll_bar_windows_size); - size_t nbytes = new_size * sizeof *scroll_bar_windows; - size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows; - - if ((size_t) -1 / sizeof *scroll_bar_windows < new_size) + ptrdiff_t new_size, old_nbytes, nbytes; + /* Check the 32-bit XClientMessageEvent limit, as well as the + usual ptrdiff_t/size_t limit. */ + if (min (0x7fffffff, + min (PTRDIFF_MAX, SIZE_MAX) / sizeof *scroll_bar_windows / 2) + < scroll_bar_windows_size) memory_full (SIZE_MAX); + new_size = max (10, 2 * scroll_bar_windows_size); + nbytes = new_size * sizeof *scroll_bar_windows; + old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows; scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows, nbytes); memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes); @@ -5813,7 +5819,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, } inev; int count = 0; int do_help = 0; - int nbytes = 0; + ptrdiff_t nbytes = 0; struct frame *f = NULL; struct coding_system coding; XEvent event = *eventptr; @@ -6511,7 +6517,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, } { /* Raw bytes, not keysym. */ - register int i; + ptrdiff_t i; int nchars, len; for (i = 0, nchars = 0; i < nbytes; i++) @@ -6524,7 +6530,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr, if (nchars < nbytes) { /* Decode the input data. */ - int require; + ptrdiff_t require; + + if (min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH + < nbytes) + memory_full (SIZE_MAX); /* The input should be decoded with `coding_system' which depends on which X*LookupString function @@ -9822,6 +9832,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) struct x_display_info *dpyinfo; XrmDatabase xrdb; Mouse_HLInfo *hlinfo; + ptrdiff_t lim; BLOCK_INPUT; @@ -10040,12 +10051,15 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) XSetAfterFunction (x_current_display, x_trace_wire); #endif /* ! 0 */ + lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@"; + if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name)) + memory_full (SIZE_MAX); dpyinfo->x_id_name = (char *) xmalloc (SBYTES (Vinvocation_name) + SBYTES (Vsystem_name) + 2); - sprintf (dpyinfo->x_id_name, "%s@%s", - SSDATA (Vinvocation_name), SSDATA (Vsystem_name)); + strcat (strcat (strcpy (dpyinfo->x_id_name, SSDATA (Vinvocation_name)), "@"), + SSDATA (Vsystem_name)); /* Figure out which modifier bits mean what. */ x_find_modifier_meanings (dpyinfo); |