From: Tobias Stoeckmann Date: Mon, 16 Mar 2026 15:00:30 +0000 (+0100) Subject: libarchive/{b64,uu}: Improve atol8 checks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ea0c525194e893b9c9cd0a9170f7049db519bca;p=thirdparty%2Flibarchive.git libarchive/{b64,uu}: Improve atol8 checks Make sure that supplied values cannot overflow int64_t, which would be an undefined behavior. Also do not accept empty strings as numbers. Last but not least, check values before casting them to target data types to avoid truncations. Signed-off-by: Tobias Stoeckmann --- diff --git a/libarchive/archive_write_add_filter_b64encode.c b/libarchive/archive_write_add_filter_b64encode.c index dbedf9d30..d2c4742d2 100644 --- a/libarchive/archive_write_add_filter_b64encode.c +++ b/libarchive/archive_write_add_filter_b64encode.c @@ -28,6 +28,9 @@ #ifdef HAVE_ERRNO_H #include #endif +#ifdef HAVE_LIMITS_H +#include +#endif #ifdef HAVE_STDLIB_H #include #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; } diff --git a/libarchive/archive_write_add_filter_uuencode.c b/libarchive/archive_write_add_filter_uuencode.c index 99c7a2cb7..d25236fa9 100644 --- a/libarchive/archive_write_add_filter_uuencode.c +++ b/libarchive/archive_write_add_filter_uuencode.c @@ -28,6 +28,9 @@ #ifdef HAVE_ERRNO_H #include #endif +#ifdef HAVE_LIMITS_H +#include +#endif #ifdef HAVE_STDLIB_H #include #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; }