]> git.ipfire.org Git - thirdparty/git.git/commitdiff
reftable/basics: handle allocation failures in `parse_names()`
authorPatrick Steinhardt <ps@pks.im>
Wed, 2 Oct 2024 10:55:38 +0000 (12:55 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 2 Oct 2024 14:53:51 +0000 (07:53 -0700)
Handle allocation failures in `parse_names()` by returning `NULL` in
case any allocation fails. While at it, refactor the function to return
the array directly instead of assigning it to an out-pointer.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
reftable/basics.c
reftable/basics.h
reftable/stack.c
t/unit-tests/t-reftable-basics.c

index 3350bbffa2384df17f6bea3f60d042e2c283cafa..ea53cf102ad529b96055b273f3ac725c349ac846 100644 (file)
@@ -135,14 +135,14 @@ size_t names_length(const char **names)
        return p - names;
 }
 
-void parse_names(char *buf, int size, char ***namesp)
+char **parse_names(char *buf, int size)
 {
        char **names = NULL;
        size_t names_cap = 0;
        size_t names_len = 0;
-
        char *p = buf;
        char *end = buf + size;
+
        while (p < end) {
                char *next = strchr(p, '\n');
                if (next && next < end) {
@@ -152,14 +152,26 @@ void parse_names(char *buf, int size, char ***namesp)
                }
                if (p < next) {
                        REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap);
-                       names[names_len++] = xstrdup(p);
+                       if (!names)
+                               goto err;
+
+                       names[names_len] = reftable_strdup(p);
+                       if (!names[names_len++])
+                               goto err;
                }
                p = next + 1;
        }
 
        REFTABLE_REALLOC_ARRAY(names, names_len + 1);
        names[names_len] = NULL;
-       *namesp = names;
+
+       return names;
+
+err:
+       for (size_t i = 0; i < names_len; i++)
+               reftable_free(names[i]);
+       reftable_free(names);
+       return NULL;
 }
 
 int names_equal(const char **a, const char **b)
index f107e1486057b07984a36ce0cc67e68ef3e5401c..69adeab2e4b6b74e46c7f5ed436f755ac9ccc925 100644 (file)
@@ -38,9 +38,12 @@ size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args);
  */
 void free_names(char **a);
 
-/* parse a newline separated list of names. `size` is the length of the buffer,
- * without terminating '\0'. Empty names are discarded. */
-void parse_names(char *buf, int size, char ***namesp);
+/*
+ * Parse a newline separated list of names. `size` is the length of the buffer,
+ * without terminating '\0'. Empty names are discarded. Returns a `NULL`
+ * pointer when allocations fail.
+ */
+char **parse_names(char *buf, int size);
 
 /* compares two NULL-terminated arrays of strings. */
 int names_equal(const char **a, const char **b);
index ce0a35216bad6d0171120e286f8a43076818d3f8..498fae846d7d45f661b4bf726c7de3f91afa7156 100644 (file)
@@ -108,7 +108,11 @@ static int fd_read_lines(int fd, char ***namesp)
        }
        buf[size] = 0;
 
-       parse_names(buf, size, namesp);
+       *namesp = parse_names(buf, size);
+       if (!*namesp) {
+               err = REFTABLE_OUT_OF_MEMORY_ERROR;
+               goto done;
+       }
 
 done:
        reftable_free(buf);
index e5556ebf527331e231d82bf6d28cf81ccb13780f..1fa77b6faff136c850b1a12d40b25ef341b8f310 100644 (file)
@@ -72,13 +72,14 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
        if_test ("parse_names works for basic input") {
                char in1[] = "line\n";
                char in2[] = "a\nb\nc";
-               char **out = NULL;
-               parse_names(in1, strlen(in1), &out);
+               char **out = parse_names(in1, strlen(in1));
+               check(out != NULL);
                check_str(out[0], "line");
                check(!out[1]);
                free_names(out);
 
-               parse_names(in2, strlen(in2), &out);
+               out = parse_names(in2, strlen(in2));
+               check(out != NULL);
                check_str(out[0], "a");
                check_str(out[1], "b");
                check_str(out[2], "c");
@@ -88,8 +89,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
 
        if_test ("parse_names drops empty string") {
                char in[] = "a\n\nb\n";
-               char **out = NULL;
-               parse_names(in, strlen(in), &out);
+               char **out = parse_names(in, strlen(in));
+               check(out != NULL);
                check_str(out[0], "a");
                /* simply '\n' should be dropped as empty string */
                check_str(out[1], "b");