]> git.ipfire.org Git - thirdparty/make.git/commitdiff
* src/arscan.c (ar_scan): [SV 54395] Allow long names in archives.
authorBen Hutchings <ben@decadent.org.uk>
Sat, 28 Jul 2018 02:31:11 +0000 (10:31 +0800)
committerPaul Smith <psmith@gnu.org>
Sat, 4 Aug 2018 21:02:21 +0000 (17:02 -0400)
Commit bc9d72beb0cb "Resolve issues discovered by static code
analysis." added range checks on archive member name length.  However,
on non-AIX systems it also checked BSD-style long names against the
short name limits and and checked the *offset* for GNU-style long
names against the short name limits.  This caused valid long names to
be rejected.

* Record the size of the GNU name map and validate offsets against it
* Ensure that the last entry in the name map is null-terminated
* Apply a maximum length of INT_MAX for element sizes

Reported-by: Philipp Wolski <philipp.wolski@kisters.de>
src/arscan.c

index 5cc5e7da9f029919d72d14164dadf1bbfcc12392..22c5438ffda3955fd67a889afaa819490d029a61 100644 (file)
@@ -416,6 +416,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
 # endif
 #endif
   char *namemap = 0;
+  int namemap_size = 0;
   int desc = open (archive, O_RDONLY, 0);
   if (desc < 0)
     return -1;
@@ -669,10 +670,15 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
               && namemap != 0)
             {
               int name_off = atoi (name + 1);
-              if (name_off < 1 || name_off > ARNAME_MAX)
+              int name_len;
+
+              if (name_off < 0 || name_off >= namemap_size)
                 goto invalid;
 
               name = namemap + name_off;
+              name_len = strlen (name);
+              if (name_len < 1)
+                goto invalid;
               long_name = 1;
             }
           else if (name[0] == '#'
@@ -680,7 +686,8 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
                    && name[2] == '/')
             {
               int name_len = atoi (name + 3);
-              if (name_len < 1 || name_len > ARNAME_MAX)
+
+              if (name_len < 1)
                 goto invalid;
 
               name = alloca (name_len + 1);
@@ -749,10 +756,13 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
             char *clear;
             char *limit;
 
-            namemap = alloca (eltsize);
+            if (eltsize > INT_MAX)
+              goto invalid;
+            namemap = alloca (eltsize + 1);
             EINTRLOOP (nread, read (desc, namemap, eltsize));
             if (nread != eltsize)
               goto invalid;
+            namemap_size = eltsize;
 
             /* The names are separated by newlines.  Some formats have
                a trailing slash.  Null terminate the strings for
@@ -767,6 +777,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
                       clear[-1] = '\0';
                   }
               }
+            *limit = '\0';
 
             is_namemap = 0;
           }