Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Regression] "die;" does not always propagate exception #11996

Closed
p5pRT opened this issue Mar 9, 2012 · 14 comments
Closed

[Regression] "die;" does not always propagate exception #11996

p5pRT opened this issue Mar 9, 2012 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Mar 9, 2012

Migrated from rt.perl.org#111654 (status was 'resolved')

Searchable as RT111654$

@p5pRT
Copy link
Author

p5pRT commented Mar 9, 2012

From anthony@derobert.net

Created by anthony@derobert.net

This is a bug report for perl from anthony@​derobert.net,
generated with the help of perlbug 1.39 running under perl 5.14.2.

-----------------------------------------------------------------

NOTE​: This is also Debian bug 663158
  http​://bugs.debian.org/cgi-bin/bugreport.cgi?bug=663158

"die" does not always propagate the exception in $@​. The below test
program should print​:

  foo at survey.cgi line 22
  main​::run_template(255490788292995187) called at survey.cgi line 18
  eval {...} called at survey.cgi line 18
  ...propagated at survey.cgi line 19.

instead it prints

  Died at survey.cgi line 19.

This worked in 5.12.x and 5.10.x.

I have tested this on Debian's compiled perl (details below from
perlbug) as well as normal 5.14.2, and also the latest development
version from git as of yesterday.

Performing a git bisect, I found the regression was introduced by

commit c5df309
Author​: Zefram <zefram@​fysh.org>
Date​: Fri Apr 23 01​:52​:47 2010 +0100

  SV-based interfaces for dieing and warning
 
  New functions croak_sv(), die_sv(), mess_sv(), and warn_sv(), each act
  much like their _sv-less counterparts, but take a single SV argument
  instead of sprintf-like format and args. They will accept RVs, passing
  them through as such. This means there's no more need to clobber ERRSV
  in order to throw a structured exception.
 
  pp_warn() and pp_die() are rewritten to use the _sv interfaces.
  This fixes part of [perl #74538]. It also means that a structured
  warning object will be passed through to $SIG{__WARN__} instead of
  being stringified, thus bringing warn in line with die with respect to
  structured exception objects.
 
  The new functions and their existing counterparts are all fully
  documented.

Test program. Note that it's very fragile. Take off -T, get rid of the
CGI->param call, do any of a bunch of other things, and it works.

===== BEGIN TEST PROGRAM =====
#!/usr/bin/perl -Tw

use Carp qw(confess);
use CGI;

my $CGI;

sub send_template;
sub run_template;

my $dat = <<DATA;
survey_no=255490788292995187
DATA
open my $fh, '<', \$dat or die "guess we don't have PerlIO";
$CGI = CGI->new($fh);
close $fh;

eval { run_template($CGI->param('survey_no')); };
die;

sub run_template {
  confess "foo";
}
===== END TEST PROGRAM =====

Note that you can find the full bisect log, the test programs used for
the bisect, etc in the Debian report at
http​://bugs.debian.org/cgi-bin/bugreport.cgi?bug=663158

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl 5.14.2:

Configured by Debian Project at Sat Mar  3 14:41:52 UTC 2012.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration:
   
  Platform:
    osname=linux, osvers=3.2.0-1-amd64, archname=x86_64-linux-gnu-thread-multi
    uname='linux madeleine 3.2.0-1-amd64 #1 smp fri feb 17 05:17:36 utc 2012 x86_64 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security -Dldflags= -Wl,-z,relro -Dlddlflags=-shared -Wl,-z,relro -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.14 -Darchlib=/usr/lib/perl/5.14 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.14.2 -Dsitearch=/usr/local/lib/perl/5.14.2 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Duse64bitint -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -Ui_libutil -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.14.2 -des'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='4.6.3', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/lib
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=, so=so, useshrplib=true, libperl=libperl.so.5.14.2
    gnulibc_version='2.13'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.14.2:
    /etc/perl
    /usr/local/lib/perl/5.14.2
    /usr/local/share/perl/5.14.2
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.14
    /usr/share/perl/5.14
    /usr/local/lib/site_perl
    .


Environment for perl 5.14.2:
    HOME=/home/anthony
    LANG=en_US.UTF-8
    LANGUAGE=en_US:en_GB:en
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/anthony/bin:/home/anthony/bin:/home/anthony/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/opt/oracle/product/11.2.0/client_1/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Mar 9, 2012

From @cpansprout

On Fri Mar 09 09​:23​:57 2012, derobert wrote​:

This is a bug report for perl from anthony@​derobert.net,
generated with the help of perlbug 1.39 running under perl 5.14.2.

-----------------------------------------------------------------

NOTE​: This is also Debian bug 663158
http​://bugs.debian.org/cgi-bin/bugreport.cgi?bug=663158

"die" does not always propagate the exception in $@​. The below test
program should print​:

foo at survey\.cgi line 22
        main&#8203;::run\_template\(255490788292995187\) called at survey\.cgi line 18
        eval \{\.\.\.\} called at survey\.cgi line 18
        \.\.\.propagated at survey\.cgi line 19\.

instead it prints

Died at survey\.cgi line 19\.

This worked in 5.12.x and 5.10.x.

I have tested this on Debian's compiled perl (details below from
perlbug) as well as normal 5.14.2, and also the latest development
version from git as of yesterday.

Performing a git bisect, I found the regression was introduced by

commit c5df309
Author​: Zefram <zefram@​fysh.org>
Date​: Fri Apr 23 01​:52​:47 2010 +0100

SV\-based interfaces for dieing and warning

New functions croak\_sv\(\)\, die\_sv\(\)\, mess\_sv\(\)\, and warn\_sv\(\)\, each

act
much like their _sv-less counterparts, but take a single SV
argument
instead of sprintf-like format and args. They will accept RVs,
passing
them through as such. This means there's no more need to clobber
ERRSV
in order to throw a structured exception.

pp\_warn\(\) and pp\_die\(\) are rewritten to use the \_sv interfaces\.
This fixes part of \[perl \#74538\]\.  It also means that a structured
warning object will be passed through to $SIG\{\_\_WARN\_\_\} instead of
being stringified\, thus bringing warn in line with die with

respect to
structured exception objects.

The new functions and their existing counterparts are all fully
documented\.

Test program. Note that it's very fragile. Take off -T, get rid of the
CGI->param call, do any of a bunch of other things, and it works.

===== BEGIN TEST PROGRAM =====
#!/usr/bin/perl -Tw

use Carp qw(confess);
use CGI;

my $CGI;

sub send_template;
sub run_template;

my $dat = <<DATA;
survey_no=255490788292995187
DATA
open my $fh, '<', \$dat or die "guess we don't have PerlIO";
$CGI = CGI->new($fh);
close $fh;

eval { run_template($CGI->param('survey_no')); };
die;

sub run_template {
confess "foo";
}
===== END TEST PROGRAM =====

That’s a pretty nasty regression. Can we make this a blocker for 5.16?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Mar 9, 2012

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Mar 10, 2012

From @tonycoz

On Fri, Mar 09, 2012 at 01​:09​:54PM -0800, Father Chrysostomos via RT wrote​:

That’s a pretty nasty regression. Can we make this a blocker for 5.16?

I think it should be a blocker too.

Tony

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

From @tonycoz

On Sat, Mar 10, 2012 at 03​:21​:29PM +1100, Tony Cook wrote​:

On Fri, Mar 09, 2012 at 01​:09​:54PM -0800, Father Chrysostomos via RT wrote​:

That’s a pretty nasty regression. Can we make this a blocker for 5.16?

I think it should be a blocker too.

Tony

A simpler test case​:

#!/usr/bin/perl -Tw
eval { die "Something tainted", $ENV{PATH} };
die;

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

From @tonycoz

On Sun, Mar 11, 2012 at 01​:19​:36PM +1100, Tony Cook wrote​:

On Sat, Mar 10, 2012 at 03​:21​:29PM +1100, Tony Cook wrote​:

On Fri, Mar 09, 2012 at 01​:09​:54PM -0800, Father Chrysostomos via RT wrote​:

That’s a pretty nasty regression. Can we make this a blocker for 5.16?

I think it should be a blocker too.

Tony

A simpler test case​:

#!/usr/bin/perl -Tw
eval { die "Something tainted", $ENV{PATH} };
die;

Attached​: regression test and possible fix.

It may be that the code should be checking for magic earlier, but with
this change the test case above behaves as with 5.10.

Tony

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

From @tonycoz

0001-rt-111654-TODO-test-for-tainted-die-propagation.patch
From 6c3816fb002c13b546764174e8576b2012725cdf Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Sun, 11 Mar 2012 14:27:29 +1100
Subject: [PATCH 1/2] [rt #111654] TODO test for tainted die propagation

---
 t/op/taint.t |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/t/op/taint.t b/t/op/taint.t
index 1b75439..095c991 100644
--- a/t/op/taint.t
+++ b/t/op/taint.t
@@ -17,7 +17,7 @@ BEGIN {
 use strict;
 use Config;
 
-plan tests => 793;
+plan tests => 794;
 
 $| = 1;
 
@@ -2197,6 +2197,15 @@ pass("no death when TARG of ref is tainted");
     is_tainted "\F$utf8", "under locale, \\Futf8 taints the result";
 }
 
+{ # 111654
+  local $::TODO = "RT #111654";
+  eval {
+    eval { die "Test\n".substr($ENV{PATH}, 0, 0); };
+    die;
+  };
+  like($@, qr/^Test\n\t\.\.\.propagated at /, "error should be propagated");
+}
+
 # This may bomb out with the alarm signal so keep it last
 SKIP: {
     skip "No alarm()"  unless $Config{d_alarm};
-- 
1.7.2.5

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

From @tonycoz

0002-rt-111654-properly-propgate-tainted-errors.patch
From e00ad30ae2b8f545e4f96cab8e76ccd74840e687 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Sun, 11 Mar 2012 14:38:57 +1100
Subject: [PATCH 2/2] [rt #111654] properly propgate tainted errors

A magic value (such as a tainted string) may not have POK set, so call
SvPV() to find out if there's something in ERRSV to report.

Possibly this should be using SvPV_nomg(), but this is the first
request for magic in this code.  Maybe the code above should be
calling SvGETMAGIC() before checking SvROK().
---
 pp_sys.c     |    2 +-
 t/op/taint.t |    1 -
 2 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/pp_sys.c b/pp_sys.c
index 63fbd05..83fe34d 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -500,7 +500,7 @@ PP(pp_die)
 	    }
 	}
     }
-    else if (SvPOK(ERRSV) && SvCUR(ERRSV)) {
+    else if (SvPV(ERRSV, len) && len) {
 	exsv = sv_mortalcopy(ERRSV);
 	sv_catpvs(exsv, "\t...propagated");
     }
diff --git a/t/op/taint.t b/t/op/taint.t
index 095c991..9cea740 100644
--- a/t/op/taint.t
+++ b/t/op/taint.t
@@ -2198,7 +2198,6 @@ pass("no death when TARG of ref is tainted");
 }
 
 { # 111654
-  local $::TODO = "RT #111654";
   eval {
     eval { die "Test\n".substr($ENV{PATH}, 0, 0); };
     die;
-- 
1.7.2.5

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

From @rjbs

This blocks 5.16.0

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

From @cpansprout

On Sat Mar 10 19​:45​:35 2012, tonyc wrote​:

On Sun, Mar 11, 2012 at 01​:19​:36PM +1100, Tony Cook wrote​:

On Sat, Mar 10, 2012 at 03​:21​:29PM +1100, Tony Cook wrote​:

On Fri, Mar 09, 2012 at 01​:09​:54PM -0800, Father Chrysostomos via
RT wrote​:

That’s a pretty nasty regression. Can we make this a blocker
for 5.16?

I think it should be a blocker too.

Tony

A simpler test case​:

#!/usr/bin/perl -Tw
eval { die "Something tainted", $ENV{PATH} };
die;

Attached​: regression test and possible fix.

It may be that the code should be checking for magic earlier, but with
this change the test case above behaves as with 5.10.

Checking for magic earlier before the SvROK check would be the correct
thing to do, not only for $@​, but also for the argument to die. But
that could be considered a separate bug, so it probably doesn’t block
5.16. I can see though, by looking at the code in pp_die, that it
doesn’t handle magic correctly in all cases. This is similar to 97480.

If you are going to use SvPV, I believe it always returns true, so what
you want (for microöptimisation), is if(SvPV(ERRSV,len), len) (note the
second comma).

Interestingly, using SvPV fixes this bug, too​:

$ perl5.14.0 -e '$@​ = 3; die'
Died at -e line 1.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

From zefram@fysh.org

Tony Cook wrote​:

- else if (SvPOK(ERRSV) && SvCUR(ERRSV)) {
+ else if (SvPV(ERRSV, len) && len) {

Yes, this looks right. There are many kinds of scalar that are not POK
right now but can PV.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

From @tonycoz

On Sat Mar 10 19​:45​:35 2012, tonyc wrote​:

Attached​: regression test and possible fix.

It may be that the code should be checking for magic earlier, but with
this change the test case above behaves as with 5.10.

Applied as af89892 and 05a1a01.

And requested in cherrymaint.

Tony

@p5pRT
Copy link
Author

p5pRT commented Mar 11, 2012

@tonycoz - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Mar 11, 2012
@p5pRT
Copy link
Author

p5pRT commented Mar 15, 2012

From @jmdh

On Sun, Mar 11, 2012 at 04​:39​:27PM -0700, Tony Cook via RT wrote​:

On Sat Mar 10 19​:45​:35 2012, tonyc wrote​:

Attached​: regression test and possible fix.

It may be that the code should be checking for magic earlier, but with
this change the test case above behaves as with 5.10.

Applied as af89892 and 05a1a01.

And requested in cherrymaint.

And queued in Debian's git (simple backport to 5.14 which just needed
adjustment for the test)​:

http​://anonscm.debian.org/gitweb/?p=perl/perl.git;a=commit;h=e6d732e0cdea0d6906b732628f6a55f93f91f633

--
Dominic Hargreaves | http​://www.larted.org.uk/~dom/
PGP key 5178E2A5 from the.earth.li (keyserver,web,email)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant