]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
string: Introduce arr_realloc() and check for integer overflow.
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 27 Oct 2021 16:11:41 +0000 (18:11 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Fri, 29 Jul 2022 17:22:09 +0000 (19:22 +0200)
Use __builtin_mul_overflow() for the check. This builtin was introduced
in gcc-5, so we need to bump the lowest supported version.

Re-implement para_realloc() as a trivial wrapper for arr_realloc()
to simplify and to avoid duplicating the size check.

12 files changed:
aft.c
audiod.c
bitstream.c
client.c
flac_afh.c
interactive.c
mood.c
mp3_afh.c
ogg_afh_common.c
string.c
string.h
web/manual.md

diff --git a/aft.c b/aft.c
index 215e8bf2c2807febd50ebe3c98e8af1ef05a1e75..991cb777e0a3bf9846d4d9aea389e03b7f6ed6a2 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1317,8 +1317,8 @@ static int prepare_ls_row(struct osl_row *row, void *ls_opts)
        if (options->num_matching_paths > options->array_size) {
                options->array_size++;
                options->array_size *= 2;
-               options->data = para_realloc(options->data, options->array_size
-                       sizeof(*options->data));
+               options->data = arr_realloc(options->data, options->array_size,
+                       sizeof(*options->data));
        }
        d = options->data + tmp;
        ret = get_afsi_of_row(aft_row, &d->afsi);
index 2a59d56a1b79c28996489bd374b407e8aeb80b65..4aef61b0160979b29ab34d398da62eab62a6a52c 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -835,12 +835,9 @@ static int add_filter(int format, const char *cmdline)
        struct lls_parse_result *flpr;
 
        filter_num = filter_setup(cmdline, &cfg, &flpr);
-       a->filter_lpr = para_realloc(a->filter_lpr,
-               (nf + 1) * sizeof(flpr));
-       a->filter_conf = para_realloc(a->filter_conf,
-               (nf + 1) * sizeof(void *));
-       a->filter_nums = para_realloc(a->filter_nums,
-               (nf + 1) * sizeof(unsigned));
+       a->filter_lpr = arr_realloc(a->filter_lpr, nf + 1, sizeof(flpr));
+       a->filter_conf = arr_realloc(a->filter_conf, nf + 1, sizeof(void *));
+       a->filter_nums = arr_realloc(a->filter_nums, nf + 1, sizeof(unsigned));
 
        a->filter_nums[nf] = filter_num;
        a->filter_conf[nf] = cfg;
index dfc1e55e67aced611014fc90b86128e8bd61a457..a1c7c943138d41993807109be09969a58e914a0b 100644 (file)
@@ -46,8 +46,8 @@ static void alloc_table(struct vlc *vlc, int size)
        vlc->table_size += size;
        if (vlc->table_size > vlc->table_allocated) {
                vlc->table_allocated += (1 << vlc->bits);
-               vlc->table = para_realloc(vlc->table,
-                       sizeof(int16_t) * 2 * vlc->table_allocated);
+               vlc->table = arr_realloc(vlc->table, vlc->table_allocated,
+                       sizeof(int16_t) * 2);
        }
 }
 
index 20c9971aa24e5818b1fb35a3be65c449670bd742..5cb2309d90d292304e26561717d9a33c2b77a20b 100644 (file)
--- a/client.c
+++ b/client.c
@@ -341,7 +341,7 @@ static void setatt_completer(struct i9e_completion_info *ci,
        if (ret < 0)
                goto out;
        num_atts = ret;
-       sl = para_realloc(sl, (2 * num_atts + 1) * sizeof(char *));
+       sl = arr_realloc(sl, 2 * num_atts + 1, sizeof(char *));
        for (i = 0; i < num_atts; i++) {
                char *orig = sl[i];
                sl[i] = make_message("%s+", orig);
index 730f954bdd80294ef406f45122d6f7cfcffbfc7b..2b5b6c1d9aa758e3d2e769756cc3d75f3bb57120 100644 (file)
@@ -374,8 +374,8 @@ static int flac_afh_read_chunks(struct private_flac_afh_data *pfad)
                        goto free_decoder;
                if (c >= chunk_table_size) {
                        chunk_table_size = 2 * chunk_table_size + 100;
-                       afhi->chunk_table = para_realloc(afhi->chunk_table,
-                               chunk_table_size * sizeof(uint32_t));
+                       afhi->chunk_table = arr_realloc(afhi->chunk_table,
+                               chunk_table_size, sizeof(uint32_t));
                }
                afhi->chunk_table[c] = pos;
 
index ee4878fb918218c4ce53b6c227132b4b45afd203..98882ce6d772c162be24ea481daf8f847eb34d5c 100644 (file)
@@ -656,8 +656,8 @@ int i9e_extract_completions(const char *word, char **string_list,
                match_count++;
                if (match_count >= matches_len) {
                        matches_len *= 2;
-                       matches = para_realloc(matches,
-                               matches_len * sizeof(char *));
+                       matches = arr_realloc(matches, matches_len,
+                               sizeof(char *));
                }
                matches[match_count - 1] = para_strdup(*p);
        }
diff --git a/mood.c b/mood.c
index 161d8df0bb344c336f0754e72b127948330bc0a3..bcc9bc57d1a37520ca71f93d5d93a7fe1e2e2927 100644 (file)
--- a/mood.c
+++ b/mood.c
@@ -363,8 +363,8 @@ static int add_if_admissible(struct osl_row *aft_row, void *data)
        if (statistics.num >= aa->size) {
                aa->size *= 2;
                aa->size += 100;
-               aa->array = para_realloc(aa->array,
-                       aa->size * sizeof(struct osl_row *));
+               aa->array = arr_realloc(aa->array, aa->size,
+                       sizeof(struct osl_row *));
        }
        aa->array[statistics.num] = aft_row;
        return add_afs_statistics(aft_row);
index 1e105b7e377b4e79e2c11df1599fa4a7270ed6cf..a42042e968a4ac696f549dfdca0229ff6a0bc313 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -633,8 +633,8 @@ static int mp3_read_info(unsigned char *map, size_t numbytes, int fd,
                total_time = tmp;
                if (afhi->chunks_total >= chunk_table_size) {
                        chunk_table_size *= 2;
-                       afhi->chunk_table = para_realloc(afhi->chunk_table,
-                               chunk_table_size * sizeof(uint32_t));
+                       afhi->chunk_table = arr_realloc(afhi->chunk_table,
+                               chunk_table_size, sizeof(uint32_t));
                }
                afhi->chunk_table[afhi->chunks_total] = fpos;
                afhi->chunks_total++;
index 3909a2916b09fb455a19b53f785d9e680bb38b13..0570656e19812ad0dbe618e599ad8539e1f21774 100644 (file)
@@ -179,9 +179,9 @@ int oac_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
                        j++;
                        if (j >= ct_size) {
                                ct_size *= 2;
-                               afhi->chunk_table = para_realloc(
+                               afhi->chunk_table = arr_realloc(
                                        afhi->chunk_table,
-                                       ct_size * sizeof(uint32_t));
+                                       ct_size, sizeof(uint32_t));
                        }
                        afhi->chunk_table[j] = oss.returned;
                }
index bbc322eb52dd2c529bd0622e84b2f2eeabe290fb..f98b199b569856d7e6df624eaf6cb1cd7ff5802e 100644 (file)
--- a/string.c
+++ b/string.c
 #include "string.h"
 #include "error.h"
 
+/**
+ * Reallocate an array, abort on failure or bugs.
+ *
+ * \param ptr Pointer to the memory block, may be NULL.
+ * \param nmemb Number of elements.
+ * \param size The size of one element in bytes.
+ *
+ * A wrapper for realloc(3) which aborts on invalid arguments or integer
+ * overflow. The wrapper also terminates the current process on allocation
+ * errors, so the caller does not need to check for failure.
+ *
+ * \return A pointer to newly allocated memory which is suitably aligned for
+ * any kind of variable and may be different from ptr.
+ *
+ * \sa realloc(3).
+ */
+__must_check void *arr_realloc(void *ptr, size_t nmemb, size_t size)
+{
+       size_t pr;
+
+       assert(size > 0);
+       assert(nmemb > 0);
+       assert(!__builtin_mul_overflow(nmemb, size, &pr));
+       assert(pr != 0);
+       ptr = realloc(ptr, pr);
+       assert(ptr);
+       return ptr;
+}
+
 /**
  * Paraslash's version of realloc().
  *
  */
 __must_check void *para_realloc(void *p, size_t size)
 {
-       /*
-        * No need to check for NULL pointers: If p is NULL, the call
-        * to realloc is equivalent to malloc(size)
-        */
-       assert(size);
-       if (!(p = realloc(p, size))) {
-               PARA_EMERG_LOG("realloc failed (size = %zu), aborting\n",
-                       size);
-               exit(EXIT_FAILURE);
-       }
-       return p;
+       return arr_realloc(p, 1, size);
 }
 
 /**
@@ -734,7 +753,7 @@ static int create_argv_offset(int offset, const char *buf, const char *delim,
                        goto err;
                if (!ret)
                        break;
-               argv = para_realloc(argv, (i + 2) * sizeof(char*));
+               argv = arr_realloc(argv, i + 2, sizeof(char*));
                argv[i] = word;
        }
        argv[i] = NULL;
index 29dc388f9373b185117974e41d3ac7c9c1c45a6b..45c359f3d56138301bf6324746ee61f7e4930cee 100644 (file)
--- a/string.h
+++ b/string.h
@@ -67,6 +67,7 @@ int for_each_line(unsigned flags, char *buf, size_t size,
 } \
 )
 
+__must_check void *arr_realloc(void *ptr, size_t nmemb, size_t size);
 __must_check void *para_realloc(void *p, size_t size);
 __must_check __malloc void *alloc(size_t size);
 __must_check __malloc void *zalloc(size_t size);
index 78834a4d48be70f178dba5ffed88f5db8761745c..b5329ea07f3d8a2f9553f384c9129c4ad1a262e3 100644 (file)
@@ -309,8 +309,8 @@ repository with
                git clone git://git.tuebingen.mpg.de/lopsub
 
 - [gcc](ftp://ftp.gnu.org/pub/gnu/gcc) or
-[clang](http://clang.llvm.org). All gcc versions >= 4.2 are currently
-supported. Clang version 1.1 or newer should work as well.
+[clang](http://clang.llvm.org). All gcc versions >= 5.4 are currently
+supported. Moderately recent versions of clang should work as well.
 
 - [gnu make](ftp://ftp.gnu.org/pub/gnu/make) is also shipped with the
 disto. On BSD systems the gnu make executable is often called gmake.