Allow curly braces to be used in pagespecs
authorJoey Hess <joey@gnu.kitenet.net>
Mon, 18 May 2009 19:25:10 +0000 (15:25 -0400)
committerJoey Hess <joey@gnu.kitenet.net>
Mon, 18 May 2009 19:25:10 +0000 (15:25 -0400)
And avoid a whole class of potential security problems (though
none that I know of actually existing..), by avoiding
performing any string interpolation on user-supplied data when translating
pagespecs.

IkiWiki.pm
debian/changelog
doc/bugs/pagespec_can__39__t_match___123__curly__125___braces.mdwn
t/pagespec_match.t

index 6233d2eada36e376ccacbc3abe140598cf9004e4..061a1c6db9f9560fb4b23766d975d4f76ccd5a45 100644 (file)
@@ -1678,12 +1678,6 @@ sub rcs_receive () {
        $hooks{rcs}{rcs_receive}{call}->();
 }
 
-sub safequote ($) {
-       my $s=shift;
-       $s=~s/[{}]//g;
-       return "q{$s}";
-}
-
 sub add_depends ($$) {
        my $page=shift;
        my $pagespec=shift;
@@ -1785,6 +1779,7 @@ sub pagespec_translate ($) {
 
        # Convert spec to perl code.
        my $code="";
+       my @data;
        while ($spec=~m{
                \s*             # ignore whitespace
                (               # 1: match a single word
@@ -1812,14 +1807,17 @@ sub pagespec_translate ($) {
                }
                elsif ($word =~ /^(\w+)\((.*)\)$/) {
                        if (exists $IkiWiki::PageSpec::{"match_$1"}) {
-                               $code.="IkiWiki::PageSpec::match_$1(\$page, ".safequote($2).", \@_)";
+                               push @data, $2;
+                               $code.="IkiWiki::PageSpec::match_$1(\$page, \$data[$#data], \@_)";
                        }
                        else {
-                               $code.="IkiWiki::ErrorReason->new(".safequote(qq{unknown function in pagespec "$word"}).")";
+                               push @data, qq{unknown function in pagespec "$word"};
+                               $code.="IkiWiki::ErrorReason->new(\$data[$#data])";
                        }
                }
                else {
-                       $code.=" IkiWiki::PageSpec::match_glob(\$page, ".safequote($word).", \@_)";
+                       push @data, $word;
+                       $code.=" IkiWiki::PageSpec::match_glob(\$page, \$data[$#data], \@_)";
                }
        }
 
index c2819d0c5c3c4e05aa2d7368bad18648410d5f87..7efa31cf1e19644a15fcc68d09c346a48b241b92 100644 (file)
@@ -6,6 +6,9 @@ ikiwiki (3.13) UNRELEASED; urgency=low
     of other underlays via add_underlay.
   * More friendly display of markdown, textile in edit form selector
     (jmtd)
+  * Allow curly braces to be used in pagespecs, and avoid a whole class
+    of potential security problems, by avoiding performing any string
+    interpolation on user-supplied data when translating pagespecs.
 
  -- Joey Hess <joeyh@debian.org>  Wed, 06 May 2009 20:45:44 -0400
 
index c03f8290767b9c2c03e55e51be1078c23e1cb712..e3146d92ae0deacd1782724fb71cb36c99cdbfa8 100644 (file)
@@ -35,6 +35,6 @@ More tests:
 > * Avoid exposing user input to interpolation as a string. One
 >   way that comes to mind is to have a local string lookup hash,
 >   and insert each user specified string into it, then use the hash
->   to lookup the specified strings at runtime.
+>   to lookup the specified strings at runtime. [[done]]
 > 
 > --[[Joey]] 
index 69cf361de4ed6aa4fa3cb591aa5c3481cab46a49..4cf6fa1ff810c2f1dc09f772b57f5f16805fa53e 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 use warnings;
 use strict;
-use Test::More tests => 51;
+use Test::More tests => 53;
 
 BEGIN { use_ok("IkiWiki"); }
 
@@ -28,6 +28,8 @@ ok(pagespec_match("a/foo", "./*", "a/b"), "relative oldstyle call");
 ok(pagespec_match("foo", "./*", location => "a"), "relative toplevel");
 ok(pagespec_match("foo/bar", "*", location => "baz"), "absolute");
 ok(! pagespec_match("foo", "foo and bar"), "foo and bar");
+ok(pagespec_match("{f}oo", "{*}*"), "curly match");
+ok(! pagespec_match("foo", "{*}*"), "curly !match");
 
 # The link and backlink stuff needs this.
 $config{userdir}="";