|
| 1 | +From 362d934368309d74829572eab884364f3e6ab475 Mon Sep 17 00:00:00 2001 |
| 2 | +From: =?UTF-8?q?ARJANEN=20Lo=C3=AFc=20Jean=20David?= <ljd@luigiscorner.mu> |
| 3 | +Date: Fri, 14 Nov 2025 20:34:48 +0100 |
| 4 | +Subject: [PATCH 1/2] Fix bsdtar zero-length pattern issue. |
| 5 | +MIME-Version: 1.0 |
| 6 | +Content-Type: text/plain; charset=UTF-8 |
| 7 | +Content-Transfer-Encoding: 8bit |
| 8 | + |
| 9 | +Uses the sed-like way (and Java-like, and .Net-like, and Javascript-like…) to fix this issue of advancing the string to be processed by one if the match is zero-length. |
| 10 | + |
| 11 | +Fixes libarchive/libarchive#2725 and solves libarchive/libarchive#2438. |
| 12 | +--- |
| 13 | + tar/subst.c | 19 ++++++++++++------- |
| 14 | + tar/test/test_option_s.c | 8 +++++++- |
| 15 | + 2 files changed, 19 insertions(+), 8 deletions(-) |
| 16 | + |
| 17 | +diff --git a/tar/subst.c b/tar/subst.c |
| 18 | +index 0194cc8..25a15d6 100644 |
| 19 | +--- a/tar/subst.c |
| 20 | ++++ b/tar/subst.c |
| 21 | +@@ -234,7 +234,9 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, |
| 22 | + (*result)[0] = 0; |
| 23 | + } |
| 24 | + |
| 25 | +- while (1) { |
| 26 | ++ char isEnd = 0; |
| 27 | ++ do { |
| 28 | ++ isEnd = *name == '\0'; |
| 29 | + if (regexec(&rule->re, name, 10, matches, 0)) |
| 30 | + break; |
| 31 | + |
| 32 | +@@ -289,12 +291,15 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, |
| 33 | + } |
| 34 | + |
| 35 | + realloc_strcat(result, rule->result + j); |
| 36 | +- |
| 37 | +- name += matches[0].rm_eo; |
| 38 | +- |
| 39 | +- if (!rule->global) |
| 40 | +- break; |
| 41 | +- } |
| 42 | ++ if (matches[0].rm_eo > 0) { |
| 43 | ++ name += matches[0].rm_eo; |
| 44 | ++ } else { |
| 45 | ++ // We skip a character because the match is 0-length |
| 46 | ++ // so we need to add it to the output |
| 47 | ++ realloc_strncat(result, name, 1); |
| 48 | ++ name += 1; |
| 49 | ++ } |
| 50 | ++ } while (rule->global && !isEnd); // Testing one step after because sed et al. run 0-length patterns a last time on the empty string at the end |
| 51 | + } |
| 52 | + |
| 53 | + if (got_match) |
| 54 | +diff --git a/tar/test/test_option_s.c b/tar/test/test_option_s.c |
| 55 | +index 1a36280..c5e75ff 100644 |
| 56 | +--- a/tar/test/test_option_s.c |
| 57 | ++++ b/tar/test/test_option_s.c |
| 58 | +@@ -42,7 +42,13 @@ DEFINE_TEST(test_option_s) |
| 59 | + systemf("%s -cf test1_2.tar -s /d1/d2/ in/d1/foo", testprog); |
| 60 | + systemf("%s -xf test1_2.tar -C test1", testprog); |
| 61 | + assertFileContents("foo", 3, "test1/in/d2/foo"); |
| 62 | +- |
| 63 | ++ systemf("%s -cf test1_3.tar -s /o/#/g in/d1/foo", testprog); |
| 64 | ++ systemf("%s -xf test1_3.tar -C test1", testprog); |
| 65 | ++ assertFileContents("foo", 3, "test1/in/d1/f##"); |
| 66 | ++ // For the 0-length pattern check, remember that "test1/" isn't part of the string affected by the regexp |
| 67 | ++ systemf("%s -cf test1_4.tar -s /f*/\\<~\\>/g in/d1/foo", testprog); |
| 68 | ++ systemf("%s -xf test1_4.tar -C test1", testprog); |
| 69 | ++ assertFileContents("foo", 3, "test1/<>i<>n<>/<>d<>1<>/<f><>o<>o<>"); |
| 70 | + /* |
| 71 | + * Test 2: Basic substitution when extracting archive. |
| 72 | + */ |
| 73 | +-- |
| 74 | +2.45.4 |
| 75 | + |
| 76 | + |
| 77 | +From 0086b1c784724f5e341991973807d8cc6fb9ba76 Mon Sep 17 00:00:00 2001 |
| 78 | +From: Martin Matuska <martin@matuska.de> |
| 79 | +Date: Mon, 8 Dec 2025 21:40:46 +0100 |
| 80 | +Subject: [PATCH 2/2] tar: fix off-bounds read resulting from #2787 (3150539ed) |
| 81 | + |
| 82 | +Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> |
| 83 | +Upstream-reference: https://github.com/libarchive/libarchive/pull/2787.patch https://patch-diff.githubusercontent.com/raw/libarchive/libarchive/pull/2809.patch |
| 84 | +--- |
| 85 | + tar/subst.c | 16 ++++++++-------- |
| 86 | + 1 file changed, 8 insertions(+), 8 deletions(-) |
| 87 | + |
| 88 | +diff --git a/tar/subst.c b/tar/subst.c |
| 89 | +index 25a15d6..df83ca2 100644 |
| 90 | +--- a/tar/subst.c |
| 91 | ++++ b/tar/subst.c |
| 92 | +@@ -236,7 +236,7 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, |
| 93 | + |
| 94 | + char isEnd = 0; |
| 95 | + do { |
| 96 | +- isEnd = *name == '\0'; |
| 97 | ++ isEnd = *name == '\0'; |
| 98 | + if (regexec(&rule->re, name, 10, matches, 0)) |
| 99 | + break; |
| 100 | + |
| 101 | +@@ -292,13 +292,13 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, |
| 102 | + |
| 103 | + realloc_strcat(result, rule->result + j); |
| 104 | + if (matches[0].rm_eo > 0) { |
| 105 | +- name += matches[0].rm_eo; |
| 106 | +- } else { |
| 107 | +- // We skip a character because the match is 0-length |
| 108 | +- // so we need to add it to the output |
| 109 | +- realloc_strncat(result, name, 1); |
| 110 | +- name += 1; |
| 111 | +- } |
| 112 | ++ name += matches[0].rm_eo; |
| 113 | ++ } else if (!isEnd) { |
| 114 | ++ // We skip a character because the match is 0-length |
| 115 | ++ // so we need to add it to the output |
| 116 | ++ realloc_strncat(result, name, 1); |
| 117 | ++ name += 1; |
| 118 | ++ } |
| 119 | + } while (rule->global && !isEnd); // Testing one step after because sed et al. run 0-length patterns a last time on the empty string at the end |
| 120 | + } |
| 121 | + |
| 122 | +-- |
| 123 | +2.45.4 |
| 124 | + |
0 commit comments