From bb359796b80d2e8bd36f6c8eafe9510874184e32 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 21 Feb 2014 17:06:36 +0000 Subject: [PATCH] protect $@ whenever a block using $@ is non-trivial As noted in the Try::Tiny man page, eval/$@ can be quite awkward in corner cases, because $@ has the same properties and problems as C's errno. While writing a regression test for definetemplate in which it couldn't find an appropriate template, I received Error: failed to process template deftmpl instead of the intended Error: failed to process template deftmpl template deftmpl not found which turned out to be because the "catch"-analogous block called gettext before it used $@, and gettext can call define_gettext, which uses eval. This commit alters all current "catch"-like blocks that use $@, except those that just do trivial things with $@ (string interpolation, string concatenation) and call a function (die, error, print, etc.) --- IkiWiki/CGI.pm | 3 ++- IkiWiki/Plugin/aggregate.pm | 8 ++++++-- IkiWiki/Plugin/attachment.pm | 6 ++++-- IkiWiki/Plugin/editpage.pm | 4 +++- IkiWiki/Plugin/edittemplate.pm | 4 +++- IkiWiki/Plugin/inline.pm | 4 +++- IkiWiki/Plugin/mdwn.pm | 3 ++- IkiWiki/Plugin/template.pm | 4 +++- 8 files changed, 26 insertions(+), 10 deletions(-) diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm index 5baa6c179..c0d8f598b 100644 --- a/IkiWiki/CGI.pm +++ b/IkiWiki/CGI.pm @@ -351,7 +351,8 @@ sub cgi_getsession ($) { { FileName => "$config{wikistatedir}/sessions.db" }) }; if (! $session || $@) { - error($@." ".CGI::Session->errstr()); + my $error = $@; + error($error." ".CGI::Session->errstr()); } umask($oldmask); diff --git a/IkiWiki/Plugin/aggregate.pm b/IkiWiki/Plugin/aggregate.pm index 28c445913..fbf88c627 100644 --- a/IkiWiki/Plugin/aggregate.pm +++ b/IkiWiki/Plugin/aggregate.pm @@ -553,7 +553,9 @@ sub aggregate (@) { }; } if ($@) { - $feed->{message}=gettext("feed crashed XML::Feed!")." ($@)"; + # gettext can clobber $@ + my $error = $@; + $feed->{message}=gettext("feed crashed XML::Feed!")." ($error)"; $feed->{error}=1; debug($feed->{message}); next; @@ -675,7 +677,9 @@ sub write_page ($$$$$) { $template=template($feed->{template}, blind_cache => 1); }; if ($@) { - print STDERR gettext("failed to process template:")." $@"; + # gettext can clobber $@ + my $error = $@; + print STDERR gettext("failed to process template:")." $error"; return; } $template->param(title => $params{title}) diff --git a/IkiWiki/Plugin/attachment.pm b/IkiWiki/Plugin/attachment.pm index 83dd120f6..d56dd18ad 100644 --- a/IkiWiki/Plugin/attachment.pm +++ b/IkiWiki/Plugin/attachment.pm @@ -229,8 +229,10 @@ sub attachment_store { check_canattach($session, $final_filename, $tempfile); }; if ($@) { - json_response($q, $form, $dest."/".$filename, $@); - error $@; + # save error in case called functions clobber $@ + my $error = $@; + json_response($q, $form, $dest."/".$filename, $error); + error $error; } # Move the attachment into holding directory. diff --git a/IkiWiki/Plugin/editpage.pm b/IkiWiki/Plugin/editpage.pm index d15607990..3047869c4 100644 --- a/IkiWiki/Plugin/editpage.pm +++ b/IkiWiki/Plugin/editpage.pm @@ -400,10 +400,12 @@ sub cgi_editpage ($$) { eval { writefile($file, $config{srcdir}, $content) }; $config{cgi}=1; if ($@) { + # save $@ in case a called function clobbers it + my $error = $@; $form->field(name => "rcsinfo", value => rcs_prepedit($file), force => 1); my $mtemplate=template("editfailedsave.tmpl"); - $mtemplate->param(error_message => $@); + $mtemplate->param(error_message => $error); $form->tmpl_param("message", $mtemplate->output); $form->field("editcontent", value => $content, force => 1); $form->tmpl_param("page_select", 0); diff --git a/IkiWiki/Plugin/edittemplate.pm b/IkiWiki/Plugin/edittemplate.pm index c7f1e4fa7..e3ce5e3d9 100644 --- a/IkiWiki/Plugin/edittemplate.pm +++ b/IkiWiki/Plugin/edittemplate.pm @@ -130,9 +130,11 @@ sub filltemplate ($$) { $template=template("/".$template_page); }; if ($@) { + # gettext can clobber $@ + my $error = $@; # Indicate that the earlier preprocessor directive set # up a template that doesn't work. - return "[[!edittemplate ".gettext("failed to process template:")." $@]]"; + return "[[!edittemplate ".gettext("failed to process template:")." $error]]"; } $template->param(name => $page); diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index 0380bec3d..123dfd364 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -391,7 +391,9 @@ sub preprocess_inline (@) { blind_cache => 1); }; if ($@) { - error sprintf(gettext("failed to process template %s"), $params{template}.".tmpl").": $@"; + # gettext can clobber $@ + my $error = $@; + error sprintf(gettext("failed to process template %s"), $params{template}.".tmpl").": $error"; } } my $needcontent=$raw || (!($archive && $quick) && $template->query(name => 'content')); diff --git a/IkiWiki/Plugin/mdwn.pm b/IkiWiki/Plugin/mdwn.pm index 430194bff..014e78eea 100644 --- a/IkiWiki/Plugin/mdwn.pm +++ b/IkiWiki/Plugin/mdwn.pm @@ -92,8 +92,9 @@ sub htmlize (@) { $markdown_sub=\&Markdown::Markdown; } else { + my $error = $@; do "/usr/bin/markdown" || - error(sprintf(gettext("failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"), $@, $!)); + error(sprintf(gettext("failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"), $error, $!)); $markdown_sub=\&Markdown::Markdown; } } diff --git a/IkiWiki/Plugin/template.pm b/IkiWiki/Plugin/template.pm index 3df06e652..ccc9cb666 100644 --- a/IkiWiki/Plugin/template.pm +++ b/IkiWiki/Plugin/template.pm @@ -41,9 +41,11 @@ sub preprocess (@) { blind_cache => 1); }; if ($@) { + # gettext can clobber $@ + my $error = $@; error sprintf(gettext("failed to process template %s"), htmllink($params{page}, $params{destpage}, - "/templates/$params{id}"))." $@"; + "/templates/$params{id}"))." $error"; } $params{basename}=IkiWiki::basename($params{page});