ijar: Avoid running past the end of a static buffer.
```
INFO: From Compiling third_party/ijar/zip_main.cc:
In file included from /usr/include/string.h:495,
from third_party/ijar/zip_main.cc:28:
In function 'char* strncpy(char*, const char*, size_t)',
inlined from 'int devtools_ijar::extract(char*, char*, char**, bool, bool, bool)' at third_party/ijar/zip_main.cc:159:12:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:34: warning: 'char* __builtin_strncpy(char*, const char*, long unsigned int)' specified bound 4096 equals destination size [-Wstringop-truncation]
106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
Closes #12292.
PiperOrigin-RevId: 341446599
diff --git a/third_party/ijar/zip_main.cc b/third_party/ijar/zip_main.cc
index b375da3..ba33a8b 100644
--- a/third_party/ijar/zip_main.cc
+++ b/third_party/ijar/zip_main.cc
@@ -80,21 +80,26 @@
};
// Concatene 2 path, path1 and path2, using / as a directory separator and
-// puting the result in "out". "size" specify the size of the output buffer
-void concat_path(char* out, const size_t size,
- const char *path1, const char *path2) {
+// putting the result in "out". "size" specify the size of the output buffer. If
+// the result would overflow the output buffer, print an error message and
+// return false.
+bool concat_path(char *out, const size_t size, const char *path1,
+ const char *path2) {
int len1 = strlen(path1);
size_t l = len1;
strncpy(out, path1, size - 1);
- out[size-1] = 0;
+ out[size - 1] = 0;
if (l < size - 1 && path1[len1] != '/' && path2[0] != '/') {
out[l] = '/';
l++;
out[l] = 0;
}
- if (l < size - 1) {
- strncat(out, path2, size - 1 - l);
+ if (l >= size - 1) {
+ fprintf(stderr, "paths too long to concat: %s + %s", path1, path2);
+ return false;
}
+ strncat(out, path2, size - 1 - l);
+ return true;
}
void UnzipProcessor::Process(const char* filename, const u4 attr,
@@ -123,8 +128,8 @@
}
if (extract_) {
char path[PATH_MAX];
- concat_path(path, PATH_MAX, output_root_, output_file_name);
- if (!make_dirs(path, perm) ||
+ if (!concat_path(path, sizeof(path), output_root_, output_file_name) ||
+ !make_dirs(path, perm) ||
(!isdir && !write_file(path, perm, data, size))) {
abort();
}
@@ -140,8 +145,8 @@
} else {
pointer++; // Skip the leading slash.
}
- strncpy(output, pointer, output_size);
- output[output_size-1] = 0;
+ strncpy(output, pointer, output_size - 1);
+ output[output_size - 1] = 0;
}
// Execute the extraction (or just listing if just v is provided)
@@ -152,11 +157,16 @@
return -1;
}
- char output_root[PATH_MAX];
+ char output_root[PATH_MAX + 1];
if (exdir != NULL) {
- concat_path(output_root, PATH_MAX, cwd.c_str(), exdir);
+ if (!concat_path(output_root, sizeof(output_root), cwd.c_str(), exdir)) {
+ return -1;
+ }
+ } else if (cwd.length() >= sizeof(output_root)) {
+ fprintf(stderr, "current working directory path too long");
+ return -1;
} else {
- strncpy(output_root, cwd.c_str(), PATH_MAX);
+ memcpy(output_root, cwd.c_str(), cwd.length() + 1);
}
UnzipProcessor processor(output_root, files, verbose, extract, flatten);