Merge pull request #2911 from stoeckmann/libarchive_opt_vals

libarchive: Check number ranges of supplied option values
(cherry picked from commit f084dfae97)
This commit is contained in:
Tim Kientzle authored and Martin Matuska committed 2026-04-13 08:38:30 +02:00
1 parent ab95301c36
commit 34b19b772b
7 files changed
+68 -18

No files matched your search

@@ -28,6 +28,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -116,12 +119,20 @@ archive_filter_b64encode_options(struct archive_write_filter *f, const char *key
struct private_b64encode *state = (struct private_b64encode *)f->data;
if (strcmp(key, "mode") == 0) {
int64_t val;
if (value == NULL) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"mode option requires octal digits");
return (ARCHIVE_FAILED);
}
state->mode = (int)atol8(value, strlen(value)) & 0777;
val = atol8(value, strlen(value));
if (val < 0 || val > INT_MAX) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"invalid mode option");
return (ARCHIVE_FAILED);
}
state->mode = (int)val & 0777;
return (ARCHIVE_OK);
} else if (strcmp(key, "name") == 0) {
if (value == NULL) {
@@ -286,14 +297,19 @@ atol8(const char *p, size_t char_cnt)
{
int64_t l;
int digit;
if (char_cnt == 0)
return (-1);
l = 0;
while (char_cnt-- > 0) {
if (*p >= '0' && *p <= '7')
digit = *p - '0';
else
break;
return (-1);
p++;
if (l > (INT64_MAX >> 3))
return (-1);
l <<= 3;
l |= digit;
}
+4 -1
View File
@@ -175,8 +175,11 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
if (strcmp(key, "original-filename") == 0) {
free((void*)data->original_filename);
data->original_filename = NULL;
if (value)
if (value) {
data->original_filename = strdup(value);
if (data->original_filename == NULL)
return (ARCHIVE_WARN);
}
return (ARCHIVE_OK);
}
+19 -3
View File
@@ -28,6 +28,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -105,12 +108,20 @@ archive_filter_uuencode_options(struct archive_write_filter *f, const char *key,
struct private_uuencode *state = (struct private_uuencode *)f->data;
if (strcmp(key, "mode") == 0) {
int64_t val;
if (value == NULL) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"mode option requires octal digits");
return (ARCHIVE_FAILED);
}
state->mode = (int)atol8(value, strlen(value)) & 0777;
val = atol8(value, strlen(value));
if (val < 0 || val > INT_MAX) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"invalid mode option");
return (ARCHIVE_FAILED);
}
state->mode = (int)val & 0777;
return (ARCHIVE_OK);
} else if (strcmp(key, "name") == 0) {
if (value == NULL) {
@@ -277,14 +288,19 @@ atol8(const char *p, size_t char_cnt)
{
int64_t l;
int digit;
if (char_cnt == 0)
return (-1);
l = 0;
while (char_cnt-- > 0) {
if (*p >= '0' && *p <= '7')
digit = *p - '0';
else
break;
return (-1);
p++;
if (l > (INT64_MAX >> 3))
return (-1);
l <<= 3;
l |= digit;
}
+7 -2
View File
@@ -29,6 +29,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -387,6 +390,7 @@ archive_compressor_xz_options(struct archive_write_filter *f,
return (ARCHIVE_OK);
} else if (strcmp(key, "threads") == 0) {
char *endptr;
unsigned long val;
if (value == NULL) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
@@ -394,13 +398,14 @@ archive_compressor_xz_options(struct archive_write_filter *f,
return (ARCHIVE_FAILED);
}
errno = 0;
data->threads = (int)strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
val = strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0' || val > (unsigned)INT_MAX) {
data->threads = 1;
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"threads invalid");
return (ARCHIVE_FAILED);
}
data->threads = (int)val;
if (data->threads == 0) {
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
data->threads = lzma_cputhreads();
+7 -2
View File
@@ -28,6 +28,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -333,6 +336,7 @@ string_to_number(const char *string, intmax_t *numberp)
if (string == NULL || *string == '\0')
return (ARCHIVE_WARN);
errno = 0;
*numberp = strtoimax(string, &end, 10);
if (end == string || *end != '\0' || errno == EOVERFLOW) {
*numberp = 0;
@@ -487,8 +491,9 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
}
char *end = NULL;
errno = 0;
long lvl = strtol(value, &end, 10);
if (end == NULL || *end != '\0') {
if (errno != 0 || end == NULL || *end != '\0') {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"parsing compression-level option value failed `%s'", value);
return (ARCHIVE_FAILED);
@@ -525,7 +530,7 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
if (string_to_number(value, &threads) != ARCHIVE_OK) {
return (ARCHIVE_WARN);
}
if (threads < 0) {
if (threads < 0 || threads > INT_MAX) {
return (ARCHIVE_WARN);
}
if (threads == 0) {
+4 -2
View File
@@ -526,12 +526,13 @@ xar_options(struct archive_write *a, const char *key, const char *value)
}
if (strcmp(key, "threads") == 0) {
char *endptr;
unsigned long val;
if (value == NULL)
return (ARCHIVE_FAILED);
errno = 0;
xar->opt_threads = (int)strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
val = strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0' || val > (unsigned)INT_MAX) {
xar->opt_threads = 1;
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
@@ -539,6 +540,7 @@ xar_options(struct archive_write *a, const char *key, const char *value)
value);
return (ARCHIVE_FAILED);
}
xar->opt_threads = (int)val;
if (xar->opt_threads == 0) {
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
xar->opt_threads = lzma_cputhreads();
+8 -5
View File
@@ -398,16 +398,17 @@ archive_write_zip_options(struct archive_write *a, const char *key,
return (ret);
} else if (strcmp(key, "compression-level") == 0) {
char *endptr;
unsigned long v;
if (val == NULL)
return (ARCHIVE_WARN);
errno = 0;
zip->compression_level = (short)strtoul(val, &endptr, 10);
if (errno != 0 || *endptr != '\0' || zip->compression_level < 0 ||
zip->compression_level > 9) {
v = strtoul(val, &endptr, 10);
if (errno != 0 || *endptr != '\0' || v > 9) {
zip->compression_level = 6; // set to default
return (ARCHIVE_WARN);
}
zip->compression_level = (short)v;
if (zip->compression_level == 0) {
zip->requested_compression = COMPRESSION_STORE;
@@ -435,17 +436,19 @@ archive_write_zip_options(struct archive_write *a, const char *key,
}
} else if (strcmp(key, "threads") == 0) {
char *endptr;
unsigned long v;
if (val == NULL)
return (ARCHIVE_FAILED);
errno = 0;
zip->threads = (short)strtoul(val, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
v = strtoul(val, &endptr, 10);
if (errno != 0 || *endptr != '\0' || v > SHRT_MAX) {
zip->threads = 1;
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Illegal value `%s'", val);
return (ARCHIVE_FAILED);
}
zip->threads = (short)v;
if (zip->threads == 0) {
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
zip->threads = lzma_cputhreads();