summaryrefslogtreecommitdiff
path: root/src/arscan.c
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2018-07-28 10:31:11 +0800
committerPaul Smith <psmith@gnu.org>2018-08-04 17:02:21 -0400
commita37fa47e3201f1239dc4fb920fc24bff43117422 (patch)
tree19ff97e3fe99d93a79abee784b7ff9c0acf16e39 /src/arscan.c
parent9ff4d6af92a2374dfb5715c2b65ba4533148d03e (diff)
downloadmake-git-a37fa47e3201f1239dc4fb920fc24bff43117422.tar.gz
* src/arscan.c (ar_scan): [SV 54395] Allow long names in archives.
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>
Diffstat (limited to 'src/arscan.c')
-rw-r--r--src/arscan.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/src/arscan.c b/src/arscan.c
index 5cc5e7da..22c5438f 100644
--- a/src/arscan.c
+++ b/src/arscan.c
@@ -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;
}