From 23a4ee6d15dbd9b8e8c6588a829dd30a26a8de32 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 18 May 2009 15:25:10 -0400 Subject: [PATCH] Allow curly braces to be used in pagespecs 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 | 16 +++++++--------- debian/changelog | 3 +++ ...__39__t_match___123__curly__125___braces.mdwn | 2 +- t/pagespec_match.t | 4 +++- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 6233d2ead..061a1c6db 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -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], \@_)"; } } diff --git a/debian/changelog b/debian/changelog index c2819d0c5..7efa31cf1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 Wed, 06 May 2009 20:45:44 -0400 diff --git a/doc/bugs/pagespec_can__39__t_match___123__curly__125___braces.mdwn b/doc/bugs/pagespec_can__39__t_match___123__curly__125___braces.mdwn index c03f82907..e3146d92a 100644 --- a/doc/bugs/pagespec_can__39__t_match___123__curly__125___braces.mdwn +++ b/doc/bugs/pagespec_can__39__t_match___123__curly__125___braces.mdwn @@ -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]] diff --git a/t/pagespec_match.t b/t/pagespec_match.t index 69cf361de..4cf6fa1ff 100755 --- a/t/pagespec_match.t +++ b/t/pagespec_match.t @@ -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}=""; -- 2.26.2