]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
libarchive: Check strto(u)l results before casts
authorTobias Stoeckmann <tobias@stoeckmann.org>
Mon, 16 Mar 2026 14:59:12 +0000 (15:59 +0100)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Mon, 16 Mar 2026 15:52:49 +0000 (16:52 +0100)
Make sure that supplied option values fit into data types. If not,
return an error instead of silently truncating values.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
libarchive/archive_write_add_filter_xz.c
libarchive/archive_write_set_format_7zip.c
libarchive/archive_write_set_format_xar.c
libarchive/archive_write_set_format_zip.c

index b80c25590e69a1d3fb354a07236792e1289a701b..56cf02070754053ef8f9dc0667048705e189fbbd 100644 (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();
index 3105cf6b2954bc8e10a4a8c52920b64180daa200..1bbd24d632e7877465904d9fca7d5e705d87d49f 100644 (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
@@ -527,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) {
index ec3219057e4ec957494ebd735f1086b2b9ac4a88..6ecccdef6499b01989339c5f250308492aa22b10 100644 (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();
index f74922ac1b9f5a696ddf70fa39b110861bbef47d..81d3db0db0383c4f8fe71a795a86ef8648861057 100644 (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();