From d985cede39843105de96b1bf91028b6ea8035365 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 3 Apr 2021 20:14:36 -0700 Subject: [PATCH] savedir: avoid unlikely undefined behavior * lib/savedir.c (streamsavedir): Prefer idx_to size_t where either will do. Simplify reallocation of entries. Use xpalloc to reallocate name_space, to avoid some unlikely integer overflows. --- ChangeLog | 6 ++++++ lib/savedir.c | 25 +++++++++---------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index d511911fdf..4a665c2753 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2021-04-03 Paul Eggert + savedir: avoid unlikely undefined behavior + * lib/savedir.c (streamsavedir): Prefer idx_to size_t where + either will do. Simplify reallocation of entries. + Use xpalloc to reallocate name_space, to avoid some unlikely + integer overflows. + quotearg: avoid undefined and/or O(N**2) Avoid undefined and O(N**2) behavior in some very unlikely cases. * lib/quotearg.c (quotearg_n_options): Document that N must diff --git a/lib/savedir.c b/lib/savedir.c index bcf41700d2..1c23d75b68 100644 --- a/lib/savedir.c +++ b/lib/savedir.c @@ -91,11 +91,11 @@ char * streamsavedir (DIR *dirp, enum savedir_option option) { char *name_space = NULL; - size_t allocated = 0; + idx_t allocated = 0; direntry_t *entries = NULL; size_t entries_allocated = 0; - size_t entries_used = 0; - size_t used = 0; + idx_t entries_used = 0; + idx_t used = 0; comparison_function cmp = comparison_function_table[option]; if (dirp == NULL) @@ -116,15 +116,12 @@ streamsavedir (DIR *dirp, enum savedir_option option) entry = dp->d_name; if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0') { - size_t entry_size = _D_EXACT_NAMLEN (dp) + 1; + idx_t entry_size = _D_EXACT_NAMLEN (dp) + 1; if (cmp) { if (entries_allocated == entries_used) - { - size_t n = entries_allocated; - entries = x2nrealloc (entries, &n, sizeof *entries); - entries_allocated = n; - } + entries = x2nrealloc (entries, &entries_allocated, + sizeof *entries); entries[entries_used].name = xstrdup (entry); #if D_INO_IN_DIRENT entries[entries_used].ino = dp->d_ino; @@ -134,13 +131,9 @@ streamsavedir (DIR *dirp, enum savedir_option option) else { if (allocated - used <= entry_size) - { - size_t n = used + entry_size; - if (n < used) - xalloc_die (); - name_space = x2nrealloc (name_space, &n, 1); - allocated = n; - } + name_space = xpalloc (name_space, &allocated, + entry_size - (allocated - used), + IDX_MAX - 1, sizeof *name_space); memcpy (name_space + used, entry, entry_size); } used += entry_size; -- 2.39.5