]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
uu: Stop processing if lines are too long (#2168)
authorTobias Stoeckmann <stoeckmann@users.noreply.github.com>
Sun, 5 May 2024 22:40:57 +0000 (00:40 +0200)
committerGitHub <noreply@github.com>
Sun, 5 May 2024 22:40:57 +0000 (15:40 -0700)
Processing excessively long lines could lead to out of boundary writes
or denial of service due to O(n^2) runtime complexity.

The OOB is properly fixed with first commit. The second commit stops
processing of lines which are longer than uu allows due to its
specification.

libarchive/archive_read_support_filter_uu.c

index 689ceb8f8760791d6b12c50aa6d21aebe29ad374..7563e861e219c00a0fc38baac7760c071e7d77bd 100644 (file)
 /* Maximum lookahead during bid phase */
 #define UUENCODE_BID_MAX_READ 128*1024 /* in bytes */
 
+#define UUENCODE_MAX_LINE_LENGTH 34*1024 /* in bytes */
+
 struct uudecode {
        int64_t          total;
        unsigned char   *in_buff;
 #define IN_BUFF_SIZE   (1024)
-       int              in_cnt;
+       ssize_t          in_cnt;
        size_t           in_allocated;
        unsigned char   *out_buff;
 #define OUT_BUFF_SIZE  (64 * 1024)
@@ -484,6 +486,12 @@ read_more:
                goto finish;
        }
        if (uudecode->in_cnt) {
+               if (uudecode->in_cnt > UUENCODE_MAX_LINE_LENGTH) {
+                       archive_set_error(&self->archive->archive,
+                           ARCHIVE_ERRNO_FILE_FORMAT,
+                           "Invalid format data");
+                       return (ARCHIVE_FATAL);
+               }
                /*
                 * If there is remaining data which is saved by
                 * previous calling, use it first.
@@ -533,7 +541,7 @@ read_more:
                                return (ARCHIVE_FATAL);
                        if (uudecode->in_buff != b)
                                memmove(uudecode->in_buff, b, len);
-                       uudecode->in_cnt = (int)len;
+                       uudecode->in_cnt = len;
                        if (total == 0) {
                                /* Do not return 0; it means end-of-file.
                                 * We should try to read bytes more. */