]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Fix bad pointer usage in xsparse.c
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 6 Nov 2024 18:18:13 +0000 (10:18 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 6 Nov 2024 18:18:55 +0000 (10:18 -0800)
* scripts/xsparse.c (read_xheader): Avoid undefined behavior by
accessing via null pointer sparse_map or out of its bounds when
the input is invalid.  This means we no longer need the â€˜expect’
local, so omit it for simplicity.

scripts/xsparse.c

index 4632e9ea4a401b80a45be6769413277b34970829..82450ea971879a95dd51b9fe9aa6a00400dbc9c2 100644 (file)
@@ -168,7 +168,6 @@ read_xheader (char *name)
 {
   char *kw, *val;
   FILE *fp = fopen (name, "r");
-  char *expect = NULL;
   size_t i = 0;
 
   if (verbose)
@@ -179,10 +178,6 @@ read_xheader (char *name)
       if (verbose)
        printf ("Found variable GNU.sparse.%s = %s\n", kw, val);
 
-      if (expect && strcmp (kw, expect))
-       die (1, "bad keyword sequence: expected '%s' but found '%s'",
-            expect, kw);
-      expect = NULL;
       if (strcmp (kw, "name") == 0)
        {
          outname = emalloc (strlen (val) + 1);
@@ -205,16 +200,25 @@ read_xheader (char *name)
        {
          sparse_map_size = string_to_size (val, NULL,
                                            SIZE_MAX / sizeof *sparse_map);
-         sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
+         if (sparse_map_size)
+           {
+             sparse_map = emalloc (sparse_map_size * sizeof *sparse_map);
+             sparse_map[0].offset = -1;
+           }
        }
       else if (strcmp (kw, "offset") == 0)
        {
+         if (sparse_map_size <= i)
+           die (1, "bad GNU.sparse.map: spurious offset");
          sparse_map[i].offset = string_to_off (val, NULL);
-         expect = "numbytes";
        }
       else if (strcmp (kw, "numbytes") == 0)
        {
+         if (sparse_map_size <= i || sparse_map[i].offset < 0)
+           die (1, "bad GNU.sparse.map: spurious numbytes");
          sparse_map[i++].numbytes = string_to_off (val, NULL);
+         if (i < sparse_map_size)
+           sparse_map[i].offset = -1;
        }
       else if (strcmp (kw, "map") == 0)
        {
@@ -238,8 +242,6 @@ read_xheader (char *name)
            die (1, "bad GNU.sparse.map: garbage at the end");
        }
     }
-  if (expect)
-    die (1, "bad keyword sequence: expected '%s' not found", expect);
   if (version_major == 0 && sparse_map_size == 0)
     die (1, "size of the sparse map unknown");
   if (i != sparse_map_size)