On Fri, 2018-07-27 at 23:41 +0800, Ben Hutchings wrote: [...] > Sorry about this. You didn't give an example to reproduce this, but I > was able to construct one. Please could you test that the attached > patch also works for your real usage? [...]
Really attached this time. Ben. -- Ben Hutchings Power corrupts. Absolute power is kind of neat. - John Lehman
From 9f15821377ec57bd36ae28eb3d430a66b87c9906 Mon Sep 17 00:00:00 2001 From: Ben Hutchings <b...@decadent.org.uk> Date: Fri, 27 Jul 2018 22:40:49 +0800 Subject: [PATCH] Fix validation of GNU-style long names in archives Commit bc9d72beb0cb "Resolve issues discovered by static code analysis." added range checks on archive member name length. However, in the case of GNU-style long names, it range-checked the *offset* in the name map as if it was a length. This caused valid long names to be rejected. * Record the size of the name map, and validate offsets against that * Ensure that the last entry in the name map is null-terminated * Check the length after finding the name in the name map Reported-by: Philipp Wolski <philipp.wol...@kisters.de> --- arscan.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arscan.c b/arscan.c index 6bc5af2467c2..f424128c2a8b 100644 --- a/arscan.c +++ b/arscan.c @@ -414,6 +414,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; @@ -667,10 +668,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 || name_len > ARNAME_MAX) + goto invalid; long_name = 1; } else if (name[0] == '#' @@ -747,10 +753,11 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg) char *clear; char *limit; - namemap = alloca (eltsize); + 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 @@ -765,6 +772,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg) clear[-1] = '\0'; } } + *limit = '\0'; is_namemap = 0; }
signature.asc
Description: This is a digitally signed message part