]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Merge pull request #2787 from ljdarj/aar
authorTim Kientzle <kientzle@acm.org>
Fri, 21 Nov 2025 05:40:17 +0000 (21:40 -0800)
committerMartin Matuska <martin@matuska.de>
Fri, 28 Nov 2025 10:47:09 +0000 (11:47 +0100)
Fix bsdtar zero-length pattern issue.

(cherry picked from commit 81bc00a549e4e0c85ab15136315ef32d70412dc7)

tar/subst.c
tar/test/test_option_s.c

index a5d644dc5a70ccfcc7c5519e082c5a2fd24db044..a466f65358a5bbff460687027049504166512a9b 100644 (file)
@@ -235,7 +235,9 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result,
                        (*result)[0] = 0;
                }
 
-               while (1) {
+               char isEnd = 0;
+               do {
+            isEnd = *name == '\0';
                        if (regexec(&rule->re, name, 10, matches, 0))
                                break;
 
@@ -290,12 +292,15 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result,
                        }
 
                        realloc_strcat(result, rule->result + j);
-
-                       name += matches[0].rm_eo;
-
-                       if (!rule->global)
-                               break;
-               }
+                       if (matches[0].rm_eo > 0) {
+                name += matches[0].rm_eo;
+            } else {
+                // We skip a character because the match is 0-length
+                // so we need to add it to the output
+                realloc_strncat(result, name, 1);
+                name += 1;
+            }
+               } 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
        }
 
        if (got_match)
index 125e971d3304b5830479a1596e2d6853663c2561..00753b99be3ca1785cd252e5c91867dab58fa196 100644 (file)
@@ -42,7 +42,13 @@ DEFINE_TEST(test_option_s)
        systemf("%s -cf test1_2.tar -s /d1/d2/ in/d1/foo", testprog);
        systemf("%s -xf test1_2.tar -C test1", testprog);
        assertFileContents("foo", 3, "test1/in/d2/foo");
-
+       systemf("%s -cf test1_3.tar -s /o/#/g in/d1/foo", testprog);
+       systemf("%s -xf test1_3.tar -C test1", testprog);
+       assertFileContents("foo", 3, "test1/in/d1/f##");
+       // For the 0-length pattern check, remember that "test1/" isn't part of the string affected by the regexp
+       systemf("%s -cf test1_4.tar -s /f*/\\<~\\>/g in/d1/foo", testprog);
+       systemf("%s -xf test1_4.tar -C test1", testprog);
+       assertFileContents("foo", 3, "test1/<>i<>n<>/<>d<>1<>/<f><>o<>o<>");
        /*
         * Test 2: Basic substitution when extracting archive.
         */