diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2018-07-28 10:31:11 +0800 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2018-08-04 17:02:21 -0400 |
commit | a37fa47e3201f1239dc4fb920fc24bff43117422 (patch) | |
tree | 19ff97e3fe99d93a79abee784b7ff9c0acf16e39 /src/arscan.c | |
parent | 9ff4d6af92a2374dfb5715c2b65ba4533148d03e (diff) | |
download | make-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.c | 17 |
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; } |