Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.87k stars 529 forks source link

die() a NOP after require() #4010

Open p5pRT opened 23 years ago

p5pRT commented 23 years ago

Migrated from rt.perl.org#7020 (status was 'open')

Searchable as RT7020$

p5pRT commented 23 years ago

From ilya@math.ohio-state.edu

Ouph\, this one took many hours to diagnose...

Here is the scoop​:

  In many situations doing die() after a require() is a kinda no-op.

  Currently I can reproduce only one such situation​:

  perl_call_*() without G_EVAL called inside eval {}\,

  but I believe many other contexts behave similarly.

Details of the control flow with the bug present​: perl_call_*() does not return (!)\, but the Perl control is quietly (without longjmp()ing out of perl_call_*() (!)) transfered to the opcode after eval {}. When the script terminates\, the C control returns to perl_call_()\, then to the code which calls perl_call_*() and so on (with most data already DESTROYed!).

Example​: dummy​::callit() is an XSUB​:

==================================================== void callit(void) {   dSP;

  PUSHMARK(SP);   perl_call_pv("mysub"\, G_DISCARD|G_NOARGS);   fprintf(stderr\, "finished call.\n"); }

MODULE = dummy PACKAGE = dummy

void callit()

Perl code is​:

==================================================== sub mysub {   require less;   die "ok 2\n" }

eval {   dummy​::callit();   warn "after!"; };

print "err​: $@​" if $@​;

This prints​:

==================================================== err​: ok 2 finished call. after! at test11.pl line 10.

Of course\, only the first line should be printed. [This is an extraction of what XML​::Encoding is doing.]



Here are the debugging details​: The bug happens when CATCH_GET() is true (this is why Perl_call_*() is doing)\, and in_eval is true too. The first condition ensures that pp_require() calls docatch(). Due to this pp_require() does not return when the end of the module is reached. Due to this\, the code after require() is still executed within the same docatch().

The second condition ensures that die_where() does not longjmp(). Then vdie() does longjmp(3)\, and docatch() essentially catches it\, and reenters again - and does not return from pp_require()/perl_call_*() - which leads to the behaviour described above.


Flags​:   category=core   severity=critical


This perlbug was built using Perl v5.6.1 - Fri May 11 16​:30​:32 PDT 2001 It is being executed now by Perl v5.6.1 - Tue May 8 02​:31​:51 PDT 2001.

Site configuration information for perl v5.6.1​:

Configured by vera at Tue May 8 02​:31​:51 PDT 2001.

Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration​:   Platform​:   osname=os2\, osvers=2.30\, archname=os2   uname='os2 ia-ia 2 2.30 i386 '   config_args='-des -D prefix=j​:/test/perllib'   hint=recommended\, useposix=true\, d_sigaction=define   usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef   useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef   use64bitint=undef use64bitall=undef uselongdouble=undef   Compiler​:   cc='gcc'\, ccflags ='-Zomf -Zmt -DDOSISH -DOS2=2 -DEMBED -I. -D_EMX_CRT_REV_=63'\,   optimize='-O2 -fomit-frame-pointer -malign-loops=2 -malign-jumps=2 -malign-functions=2 -s'\,   cppflags='-Zomf -Zmt -DDOSISH -DOS2=2 -DEMBED -I. -D_EMX_CRT_REV_=63'   ccversion=''\, gccversion='2.8.1'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=4   alignbytes=4\, usemymalloc=y\, prototype=define   Linker and Libraries​:   ld='gcc'\, ldflags ='-Zexe -Zomf -Zmt -Zcrtdll -Zstack 32000'   libpth=i​:/emx.add/lib i​:/emx/lib D​:/DEVTOOLS/OPENGL/LIB I​:/JAVA11/LIB i​:/emx/lib/mt   libs=-lsocket -lm -lbsd   perllibs=-lsocket -lm -lbsd   libc=i​:/emx/lib/mt/c_import.lib\, so=dll\, useshrplib=true\, libperl=libperl.lib   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags='-Zdll'\, lddlflags='-Zdll -Zomf -Zmt -Zcrtdll -s'

Locally applied patches​:  


@​INC for perl v5.6.1​:   j​:/test/perllib/lib/5.6.1/os2   j​:/test/perllib/lib/5.6.1   j​:/test/perllib/lib/site_perl/5.6.1/os2   j​:/test/perllib/lib/site_perl/5.6.1   j​:/test/perllib/lib/site_perl   .


Environment for perl v5.6.1​:   HOME=j​:/home   LANG=EN_US   LANGUAGE (unset)   LD_LIBRARY_PATH (unset)   LOGDIR (unset)   PATH=[censored]   PERLLIB_PREFIX=f​:/perllib;i​:/perllib   PERL_BADLANG (unset)   PERL_SH_DIR=i​:/bin   SHELL (unset)

p5pRT commented 23 years ago

From [Unknown Contact. See original ticket]

Since doing croak() will call a die() after require Carp​::Heavy\, the failing sequence may be as easy as

  From eval {}   call an XSUB   which calls (without G_EVAL) a Perl subroutine   which croak()s

[Un]fortunately\, all XSUBs from Perl distribution which call Perl subroutines without G_EVAL do it from a "tie()ed method" context\, which replaces Perl stack\, and the above bug is not triggered when a stack is replaced.

There is only one exception - DProf. However\, (due to some DProf obfuscations?) I cannot see the effects of the bug with just calling croak(). However\, 'require less and die' shows the problem (segfault on my system\, I think it could print 12 nn some of other systems\, with other malloc()s).

perl -d​:Dprof -wle "   sub f {require less; die 'OO'} eval {f; print 12} or warn; print 13"

Hope this helps\, Ilya