Avoid processing invalid directive elements
authorJacob Bachmeyer <jcb@gnu.org>
Thu, 27 Oct 2022 03:46:47 +0000 (22:46 -0500)
committerJacob Bachmeyer <jcb@gnu.org>
Thu, 27 Oct 2022 03:46:47 +0000 (22:46 -0500)
The old code simply abandoned the entire loop at the first error; this
meant that a "directory" element after an error would not be seen and was
fixed in commit 86b458910ddda2c227622cafa3c37b10682d0561.  That commit
allowed the values of the capture variables from the last successful match
to be reused if a later line did not match its filter pattern.

No exploit was possible, since an error was recorded and an exception would
be thrown instead of returning the corrupted operation list, but this had
side effects that caused failures in the testsuite that were traced to this
issue, now fixed.

gatekeeper.pl

index b50a07f37b35819427f923260c3e9ea2e94df78f..9e54469ebe2d2fcadc9f8c8847775816897d844b 100755 (executable)
@@ -1687,8 +1687,10 @@ sub interpret_directive {
       $header{package} = $info{package};
     } elsif ($tainted_cmd eq 'filename') {
       # We use the same filename restrictions as scan_incoming
-      $tainted_val =~ /^($RE_filename_here)$/
-       or push @errors, "invalid filename $tainted_val";
+      unless ($tainted_val =~ /^($RE_filename_here)$/) {
+       push @errors, "invalid filename $tainted_val";
+       next;
+      }
       my $val = $1;  # so far so good
 
       # Only let them specify one filename directive.
@@ -1702,29 +1704,36 @@ sub interpret_directive {
     } elsif ($tainted_cmd eq 'version') {
       # already handled above
     } elsif ($tainted_cmd eq 'symlink') {
-      $tainted_val =~ /^($RE_filename_relative)\s+($RE_filename_relative)$/
-       or push @errors,
-         "invalid parameters for symlink command: $tainted_val";
+      unless ($tainted_val =~
+             /^($RE_filename_relative)\s+($RE_filename_relative)$/) {
+       push @errors, "invalid parameters for symlink command: $tainted_val";
+       next;
+      }
       # $1 -- link target      $2 -- link name
       push @ops, [symlink => $1, $2];
       $info{"symlink-$1"} = {"link" => $2, "order" => $cnt++}; #ok.
     } elsif ($tainted_cmd eq 'rmsymlink') {
-      $tainted_val =~ /^($RE_filename_relative)$/
-       or push @errors,
-         "invalid parameters for rmsymlink command: $tainted_val";
+      unless ($tainted_val =~ /^($RE_filename_relative)$/) {
+       push @errors, "invalid parameters for rmsymlink command: $tainted_val";
+       next;
+      }
       push @ops, [rmsymlink => $1];
       $info{"rmsymlink-$1"} = {"order" => $cnt++}; #ok.
     } elsif ($tainted_cmd eq 'archive') {
-      $tainted_val =~ /^($RE_filename_relative)$/
-       or push @errors,
+      unless ($tainted_val =~ /^($RE_filename_relative)$/) {
+       push @errors,
          "invalid parameters for archive command: $tainted_val";
+       next;
+      }
       push @ops, [archive => $1];
       $info{"archive-$1"} = {"order" => $cnt++}; #ok.
     } elsif ($tainted_cmd eq 'replace') {
       # This command is only supported from v1.2
-      $tainted_val =~ /^(true|false)$/
-       or push @errors,
+      unless ($tainted_val =~ /^(true|false)$/) {
+       push @errors,
          "invalid parameters for replace command: $tainted_val";
+       next;
+      }
 
       push @errors,
        "invalid directive 'replace', not supported prior to version 1.2"