Prefer ptrdiff_t to size_t when either will do

Signed types are a bit safer, as they avoid some comparison confusion
and -fsanitize=undefined can check more misuses of them.
* src/alloc.c (lisp_malloc, lisp_align_malloc)
(allocate_string_data, allocate_vector_from_block, object_bytes):
* src/coding.c (from_unicode_buffer):
* src/decompress.c (acc_size, accumulate_and_process_md5):
* src/emacs.c (load_seccomp, shut_down_emacs):
* src/fns.c (sxhash_bignum):
* src/ftfont.c (get_adstyle_property):
* src/image.c (lookup_image, xpm_init_color_cache)
(xpm_cache_color):
* src/json.c (json_out_str, struct json_parser)
(json_make_object_workspace_for_slow_path)
(json_make_object_workspace_for, json_parse_array)
(json_parse_object):
* src/sysdep.c (get_current_dir_name_or_unreachable)
(init_sys_modes, convert_speed):
* src/termchar.h (struct tty_display_info):
* src/textconv.h (struct textconv_conversion_text):
* src/xfns.c (struct x_xim_text_conversion_data)
(x_encode_xim_text):
* src/xselect.c (struct transfer, c_size_for_format)
(x_size_for_format, selection_data_for_offset)
(selection_data_size, x_start_selection_transfer)
(x_continue_selection_transfer):
Prefer ptrdiff_t to size_t when either will do.
* src/term.c (Ftty__set_output_buffer_size):
Limit output buffer size to PTRDIFF_MAX as well as to SIZE_MAX.
This commit is contained in:
Paul Eggert 2026-05-23 09:59:25 -07:00
parent 82ad01b631
commit 2e91ed5f12
14 changed files with 71 additions and 82 deletions

View file

@ -899,7 +899,7 @@ void *lisp_malloc_loser EXTERNALLY_VISIBLE;
L == make_lisp_ptr (P, T), then XPNTR (L) == P and XTYPE (L) == T. */
static void *
lisp_malloc (size_t nbytes, bool clearit, enum mem_type type)
lisp_malloc (ptrdiff_t nbytes, bool clearit, enum mem_type type)
{
register void *val;
@ -1083,7 +1083,7 @@ pointer_align (void *ptr, int alignment)
Alignment is on a multiple of BLOCK_ALIGN and `nbytes' has to be
smaller or equal to BLOCK_BYTES. */
static void *
lisp_align_malloc (size_t nbytes, enum mem_type type)
lisp_align_malloc (ptrdiff_t nbytes, enum mem_type type)
{
void *base, *val;
struct ablocks *abase;
@ -1522,7 +1522,7 @@ sdata_size (ptrdiff_t n)
/* Exact bound on the number of bytes in a string, not counting the
terminating null. A string cannot contain more bytes than
STRING_BYTES_BOUND, nor can it be so long that the size_t
STRING_BYTES_BOUND, nor can it be so long that the
arithmetic in allocate_string_data would overflow while it is
calculating a value to be passed to malloc. */
static ptrdiff_t const STRING_BYTES_MAX =
@ -1768,7 +1768,7 @@ allocate_string_data (struct Lisp_String *s,
if (nbytes > LARGE_STRING_BYTES || immovable)
{
size_t size = FLEXSIZEOF (struct sblock, data, needed);
ptrdiff_t size = FLEXSIZEOF (struct sblock, data, needed);
#ifdef DOUG_LEA_MALLOC
if (!mmap_lisp_allowed_p ())
@ -2996,7 +2996,7 @@ allocate_vector_from_block (ptrdiff_t nbytes)
{
struct Lisp_Vector *vector;
struct vector_block *block;
size_t index, restbytes;
ptrdiff_t index, restbytes;
eassume (VBLOCK_BYTES_MIN <= nbytes && nbytes <= VBLOCK_BYTES_MAX);
eassume (nbytes % roundup_size == 0);
@ -3022,7 +3022,7 @@ allocate_vector_from_block (ptrdiff_t nbytes)
{
/* This vector is larger than requested. */
vector = vector_free_lists[index];
size_t vector_nbytes = pseudovector_nbytes (&vector->header);
ptrdiff_t vector_nbytes = pseudovector_nbytes (&vector->header);
eassert (vector_nbytes > nbytes);
ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
vector_free_lists[index] = next_vector (vector);
@ -5465,10 +5465,10 @@ inhibit_garbage_collection (void)
}
/* Return the number of bytes in N objects each of size S, guarding
against overflow if size_t is narrower than byte_ct. */
against overflow if ptrdiff_t is narrower than byte_ct. */
static byte_ct
object_bytes (object_ct n, size_t s)
object_bytes (object_ct n, ptrdiff_t s)
{
byte_ct b = s;
return n * b;

View file

@ -8554,19 +8554,17 @@ from_unicode_buffer (const wchar_t *wstr)
strings are extended to 32-bit wchar_t. */
uint16_t *words;
size_t length, i;
length = wcslen (wstr) + 1;
ptrdiff_t length = wcslen (wstr);
USE_SAFE_ALLOCA;
SAFE_NALLOCA (words, sizeof *words, length);
SAFE_NALLOCA (words, sizeof *words, length + 1);
for (i = 0; i < length - 1; ++i)
for (ptrdiff_t i = 0; i < length; i++)
words[i] = wstr[i];
words[length] = '\0';
words[i] = '\0';
AUTO_STRING_WITH_LEN (str, (char *) words,
(length - 1) * sizeof *words);
length * sizeof *words);
return unbind_to (sa_count, from_unicode (str));
#endif
}

View file

@ -70,10 +70,10 @@ init_zlib_functions (void)
# define MD5_BLOCKSIZE 32768 /* From md5.c */
static char acc_buff[2 * MD5_BLOCKSIZE];
static size_t acc_size;
static ptrdiff_t acc_size;
static void
accumulate_and_process_md5 (void *data, size_t len, struct md5_ctx *ctxt)
accumulate_and_process_md5 (void *data, ptrdiff_t len, struct md5_ctx *ctxt)
{
eassert (len <= MD5_BLOCKSIZE);
/* We may optimize this saving some of these memcpy/move using

View file

@ -1235,39 +1235,33 @@ load_seccomp (const char *file)
file, (long) stat.st_size);
goto out;
}
size_t size = stat.st_size;
size_t count = size / sizeof *program.filter;
eassert (0 < count && count < SIZE_MAX);
if (USHRT_MAX < count)
if (ckd_add (&program.len, stat.st_size / sizeof *program.filter, 0))
{
fprintf (stderr, "seccomp filter %s is too big\n", file);
goto out;
}
/* Try reading one more byte to detect file size changes. */
ptrdiff_t size = stat.st_size;
buffer = malloc (size + 1);
if (buffer == NULL)
{
emacs_perror ("malloc");
goto out;
}
ptrdiff_t read = read_full (fd, buffer, size + 1);
if (read < 0)
ptrdiff_t nread = read_full (fd, buffer, size + 1);
if (nread != size)
{
emacs_perror ("read");
goto out;
}
eassert (read <= SIZE_MAX);
if (read != size)
{
fprintf (stderr,
"seccomp filter %s changed size while reading\n",
file);
if (nread < 0)
emacs_perror ("read");
else
fprintf (stderr,
"seccomp filter %s changed size while reading\n",
file);
goto out;
}
if (emacs_close (fd) != 0)
emacs_perror ("close"); /* not a fatal error */
fd = -1;
program.len = count;
program.filter = buffer;
/* See man page of `seccomp' why this is necessary. Note that we
@ -3131,7 +3125,7 @@ shut_down_emacs (int sig, Lisp_Object stuff)
+ INT_STRLEN_BOUND (int) + 1),
min (PIPE_BUF, MAX_ALLOCA))];
char const *sig_desc = safe_strsignal (sig);
size_t sig_desclen = strlen (sig_desc);
ptrdiff_t sig_desclen = strlen (sig_desc);
int nlen = sprintf (buf, fmt, sig);
if (nlen + sig_desclen < sizeof buf - 1)
{

View file

@ -5480,10 +5480,10 @@ static EMACS_UINT
sxhash_bignum (Lisp_Object bignum)
{
mpz_t const *n = xbignum_val (bignum);
size_t i, nlimbs = mpz_size (*n);
EMACS_UINT hash = mpz_sgn(*n) < 0;
ptrdiff_t nlimbs = mpz_size (*n);
EMACS_UINT hash = mpz_sgn (*n) < 0;
for (i = 0; i < nlimbs; ++i)
for (ptrdiff_t i = 0; i < nlimbs; i++)
hash = sxhash_combine (hash, mpz_getlimbn (*n, i));
return hash;

View file

@ -150,7 +150,6 @@ get_adstyle_property (FcPattern *p)
{
FcChar8 *fcstr;
char *str, *end, *tmp;
size_t i;
Lisp_Object adstyle;
#ifdef FC_FONTFORMAT
@ -173,7 +172,7 @@ get_adstyle_property (FcPattern *p)
and therefore must be replaced by substitutes. (bug#70989) */
USE_SAFE_ALLOCA;
tmp = SAFE_ALLOCA (end - str);
for (i = 0; i < end - str; ++i)
for (ptrdiff_t i = 0; i < end - str; i++)
tmp[i] = ((str[i] != '?'
&& str[i] != '*'
&& str[i] != '"'

View file

@ -3562,7 +3562,7 @@ lookup_image (struct frame *f, Lisp_Object spec, int face_id)
img->face_font_size = font_size;
img->face_font_height = face->font->height;
img->face_font_width = face->font->average_width;
size_t len = strlen (font_family) + 1;
ptrdiff_t len = strlen (font_family) + 1;
img->face_font_family = xmalloc (len);
memcpy (img->face_font_family, font_family, len);
img->load_failed_p = ! img->type->load_img (f, img);
@ -5538,7 +5538,7 @@ static struct xpm_cached_color **xpm_color_cache;
static void
xpm_init_color_cache (struct frame *f, XpmAttributes *attrs)
{
size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
ptrdiff_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
xpm_color_cache = xzalloc (nbytes);
init_color_table ();
@ -5598,8 +5598,8 @@ xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket)
if (bucket < 0)
bucket = xpm_color_bucket (color_name);
size_t len = strlen (color_name) + 1;
size_t nbytes = FLEXSIZEOF (struct xpm_cached_color, name, len);
ptrdiff_t len = strlen (color_name) + 1;
ptrdiff_t nbytes = FLEXSIZEOF (struct xpm_cached_color, name, len);
struct xpm_cached_color *p = xmalloc (nbytes);
memcpy (p->name, color_name, len);
p->color = *color;

View file

@ -273,7 +273,7 @@ json_make_room (json_out_t *jo, ptrdiff_t bytes)
/* Add `bytes` bytes from `str` to the buffer. */
static void
json_out_str (json_out_t *jo, const char *str, size_t bytes)
json_out_str (json_out_t *jo, const char *str, ptrdiff_t bytes)
{
json_make_room (jo, bytes);
memcpy (jo->buf + jo->size, str, bytes);
@ -693,7 +693,7 @@ struct json_parser
struct json_configuration conf;
size_t additional_bytes_count;
ptrdiff_t additional_bytes_count;
/* Lisp_Objects are collected in this area during object/array
parsing. To avoid allocations, initially
@ -704,8 +704,8 @@ struct json_parser
Lisp_Object internal_object_workspace
[JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE];
Lisp_Object *object_workspace;
size_t object_workspace_size;
size_t object_workspace_current;
ptrdiff_t object_workspace_size;
ptrdiff_t object_workspace_current;
/* String and number parsing uses this workspace. The idea behind
internal_byte_workspace is the same as the idea behind
@ -805,10 +805,9 @@ json_make_object_workspace_for_slow_path (struct json_parser *parser,
{
bool internal = (parser->object_workspace_size
== JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE);
ptrdiff_t new_workspace_size = parser->object_workspace_size;
Lisp_Object *new_workspace_ptr
= xpalloc (internal ? NULL : parser->object_workspace,
&new_workspace_size,
&parser->object_workspace_size,
size - (parser->object_workspace_size
- parser->object_workspace_current),
-1, sizeof (Lisp_Object));
@ -816,12 +815,11 @@ json_make_object_workspace_for_slow_path (struct json_parser *parser,
memcpy (new_workspace_ptr, parser->object_workspace,
sizeof (Lisp_Object) * parser->object_workspace_current);
parser->object_workspace = new_workspace_ptr;
parser->object_workspace_size = new_workspace_size;
}
INLINE void
json_make_object_workspace_for (struct json_parser *parser,
size_t size)
ptrdiff_t size)
{
if (parser->object_workspace_size - parser->object_workspace_current
< size)
@ -1350,7 +1348,7 @@ json_parse_array (struct json_parser *parser)
{
int c = json_skip_whitespace (parser);
const size_t first = parser->object_workspace_current;
const ptrdiff_t first = parser->object_workspace_current;
Lisp_Object result = Qnil;
if (c != ']')
@ -1402,10 +1400,10 @@ json_parse_array (struct json_parser *parser)
{
case json_array_array:
{
size_t number_of_elements
ptrdiff_t number_of_elements
= parser->object_workspace_current - first;
result = make_vector (number_of_elements, Qnil);
for (size_t i = 0; i < number_of_elements; i++)
for (ptrdiff_t i = 0; i < number_of_elements; i++)
{
rarely_quit (i);
ASET (result, i, parser->object_workspace[first + i]);
@ -1441,7 +1439,7 @@ json_parse_object (struct json_parser *parser)
{
int c = json_skip_whitespace (parser);
const size_t first = parser->object_workspace_current;
const ptrdiff_t first = parser->object_workspace_current;
Lisp_Object result = Qnil;
if (c != '}')
@ -1517,10 +1515,10 @@ json_parse_object (struct json_parser *parser)
{
case json_object_hashtable:
{
EMACS_INT value = (parser->object_workspace_current - first) / 2;
EMACS_INT value = (parser->object_workspace_current - first) >> 1;
result = make_hash_table (&hashtest_equal, value, Weak_None);
struct Lisp_Hash_Table *h = XHASH_TABLE (result);
for (size_t i = first; i < parser->object_workspace_current; i += 2)
for (ptrdiff_t i = first; i < parser->object_workspace_current; i += 2)
{
hash_hash_t hash;
Lisp_Object key = parser->object_workspace[i];

View file

@ -304,7 +304,7 @@ get_current_dir_name_or_unreachable (void)
}
# endif
size_t pwdlen;
ptrdiff_t pwdlen;
struct stat dotstat, pwdstat;
pwd = getenv ("PWD");
@ -1310,9 +1310,9 @@ init_sys_modes (struct tty_display_info *tty_out)
}
#endif /* F_GETOWN */
const size_t buffer_size = (tty_out->output_buffer_size
? tty_out->output_buffer_size
: BUFSIZ);
const ptrdiff_t buffer_size = (tty_out->output_buffer_size
? tty_out->output_buffer_size
: BUFSIZ);
setvbuf (tty_out->output, NULL, _IOFBF, buffer_size);
if (tty_out->terminal->set_terminal_modes_hook)
@ -3136,7 +3136,7 @@ static const struct speed_struct speeds[] =
static speed_t
convert_speed (speed_t speed)
{
for (size_t i = 0; i < ARRAYELTS (speeds); i++)
for (ptrdiff_t i = 0; i < ARRAYELTS (speeds); i++)
{
if (speed == speeds[i].internal)
return speed;

View file

@ -2613,7 +2613,7 @@ This function temporarily suspends and resumes the terminal
device. */)
(Lisp_Object size, Lisp_Object tty)
{
if (!TYPE_RANGED_FIXNUMP (size_t, size))
if (!RANGED_FIXNUMP (0, size, min (PTRDIFF_MAX, SIZE_MAX)))
error ("Invalid output buffer size");
Fsuspend_tty (tty);
struct terminal *terminal = decode_tty_terminal (tty);

View file

@ -56,7 +56,7 @@ struct tty_display_info
/* Size of output buffer. A value of zero means use the default of
BUFIZE. If non-zero, also minimize writes to the tty by avoiding
calls to flush. */
size_t output_buffer_size;
ptrdiff_t output_buffer_size;
FILE *termscript; /* If nonzero, send all terminal output
characters to this stream also. */

View file

@ -80,7 +80,7 @@ enum textconv_operation
struct textconv_conversion_text
{
/* Length of the text in characters and bytes. */
size_t length, bytes;
ptrdiff_t length, bytes;
/* Pointer to the text data. This must be deallocated by the
caller. */

View file

@ -3467,7 +3467,7 @@ struct x_xim_text_conversion_data
struct coding_system *coding;
char *source;
struct x_display_info *dpyinfo;
size_t size;
ptrdiff_t size;
};
static Lisp_Object
@ -3600,7 +3600,7 @@ x_xim_text_to_utf8_unix (struct x_display_info *dpyinfo,
static char *
x_encode_xim_text (struct x_display_info *dpyinfo, char *text,
size_t size, ptrdiff_t *length,
ptrdiff_t size, ptrdiff_t *length,
ptrdiff_t *chars)
{
struct coding_system coding;

View file

@ -522,7 +522,7 @@ struct transfer
/* The current offset in items into the selection data, and the
number of items to send with each ChangeProperty request. */
size_t offset, items_per_request;
ptrdiff_t offset, items_per_request;
/* The display info associated with the transfer. */
struct x_display_info *dpyinfo;
@ -669,7 +669,7 @@ x_selection_request_lisp_error (void)
static size_t
static ptrdiff_t
c_size_for_format (int format)
{
switch (format)
@ -687,7 +687,7 @@ c_size_for_format (int format)
emacs_abort ();
}
static size_t
static ptrdiff_t
x_size_for_format (int format)
{
switch (format)
@ -712,10 +712,10 @@ x_size_for_format (int format)
static unsigned char *
selection_data_for_offset (struct selection_data *data,
size_t offset, size_t *remaining)
ptrdiff_t offset, ptrdiff_t *remaining)
{
unsigned char *base;
size_t size;
ptrdiff_t size;
if (!NILP (data->string))
{
@ -746,10 +746,10 @@ selection_data_for_offset (struct selection_data *data,
FIXME: Silent truncation is bad. */
static size_t
static ptrdiff_t
selection_data_size (struct selection_data *data)
{
size_t scratch;
ptrdiff_t scratch;
ptrdiff_t max_selection_size = min (min (PTRDIFF_MAX, SIZE_MAX),
X_ULONG_MAX);
@ -856,7 +856,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor,
intmax_t timeout;
intmax_t secs;
int nsecs;
size_t remaining, max_size;
ptrdiff_t remaining, max_size;
unsigned char *xdata;
unsigned long data_size;
@ -892,9 +892,9 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor,
max_size = selection_quantum (dpyinfo->display);
size_t seldata_size = selection_data_size (&transfer->data);
ptrdiff_t seldata_size = selection_data_size (&transfer->data);
TRACE3 (" x_start_selection_transfer: transferring to 0x%lx. "
"transfer consists of %zu bytes, quantum being %zu",
"transfer consists of %tu bytes, quantum being %tu",
requestor, seldata_size, max_size);
if (max_size < seldata_size)
@ -905,7 +905,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor,
transfer->items_per_request
= (max_size / x_size_for_format (transfer->data.format));
TRACE1 (" x_start_selection_transfer: starting incremental"
" selection transfer, with %zu items per request",
" selection transfer, with %tu items per request",
transfer->items_per_request);
/* Next, link the transfer onto the list of pending selection
@ -954,7 +954,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor,
eassert (remaining <= INT_MAX);
TRACE1 (" x_start_selection_transfer: writing"
" %zu elements directly to requestor window",
" %tu elements directly to requestor window",
remaining);
x_ignore_errors_for_next_request (dpyinfo, 0);
@ -977,7 +977,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor,
static void
x_continue_selection_transfer (struct transfer *transfer)
{
size_t remaining;
ptrdiff_t remaining;
unsigned char *xdata;
xdata = selection_data_for_offset (&transfer->data,
@ -1006,8 +1006,8 @@ x_continue_selection_transfer (struct transfer *transfer)
}
else
{
TRACE2 (" x_continue_selection_transfer: writing %zu items"
"; current offset is %zu", remaining, transfer->offset);
TRACE2 (" x_continue_selection_transfer: writing %tu items"
"; current offset is %tu", remaining, transfer->offset);
eassert (remaining <= INT_MAX);
transfer->offset += remaining;