Skip Menu |
Report information
Id: 108276
Status: open
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: bulk88 <bulk88 [at] hotmail.com>
Cc:
AdminCc:

Operating System: mswin32
PatchStatus: HasPatch
Severity: High
Type: core
Perl Version: 5.12.2
Fixed In: (no value)

Attachments
0001-fix-PERL_OP_PARENT-builds.patch
0001-perl-108276-avoid-deep-recursion-in-Perl_op_free.patch
0001-perl-108276-avoid-deep-scalarvoid-self-recursion.patch
0001-perl-108276-avoid-recursion-in-S_finalize_op.patch
0001-perl-108276-use-the-PERL_OP_PARENT-links-in-S_finali.patch
0002-perl-108276-re-indent-the-loop-body.patch
0002-perl-108276-re-indent-the-new-S_finalize_op-loop.patch
0003-perl-108276-use-the-new-declare-and-clean-up-macros-.patch
108276_stk.pl
davem S_finalize_op callstack.txt
fault-free-op.diff
for.t.stk.txt
io.fs.t.stk.txt
op-free-defer.diff
perlmain.c
perlstackcrash.txt
perlstk1.PNG
perlstk2.png
plstk1.txt
re.pat_advanced.t.stk.pl
rep op on evaled add callstack.txt
scalarvoid callstack.txt
stk.pl



Subject: C stack overflow in Perl_scalarvoid
Date: Sun, 15 Jan 2012 13:34:58 -0500
To: <perlbug [...] perl.org>
From: bulk 88 <bulk88 [...] hotmail.com>
Download (untitled) / with headers
text/plain 5.6k
This is a bug report for perl from bulk88@hotmail.com, generated with the help of perlbug 1.39 running under perl 5.12.2. ----------------------------------------------------------------- [Please describe your issue here] Perl lexer (???) has a deep recursion bug in Perl_scalarvoid when given a very large Perl subroutine to run.  Perl_scalarvoid calls itself over and over, for what I blindly guess is every opcode in the sub.  If there are too many opcodes, C stack overflows. I could not replicate this with any stock ActivePerl (AP 5.10.0, AP 5.12.3).  While the test script is running, ActivePerls peak at 8 MB on the C stack.  I checked with VMMAP.  If I lower the stack reserve from 16 MB to 256KB in the PE header on perl.exe from ActivePerls, I will get the same exact Perl_scalarvoid stack overflow.  There is no reason for the interpreter to peak at many MBs of C stack, which is irreversibly expanded (there are OS specific ways to shrink C stacks.... I know it can be done with VirtualFree and VirtualAlloc on Windows, but that is the wrong way to fix C stack recursion) and wasted, never to be used again after BEGIN blocks run.  I have not tested doing the "require" at runtime.  On other perl scripts and apps I run, all the interpreter (APs and my compiled Perl) peak at 20-50KB of C stack which is fine.  I assume that the reason that my self-compiled Perl will stack overflow at 16MB and ActivePerls do not is because of high C stack overhead of each recursive Perl_scalarvoid when Perl is compiled with -Od (no registers) meanwhile ActivePerls are compiled with -O1 (small code). I wrote this test script to test how efficient Perl is at returning memory to the OS after a Perl Module is "use"d and if, and how well, memory behind the BEGIN blocks (SVs, CVs, Opcodes, pads, raw malloced blocks) is returned to the OS.  If I lower the 100000 to 50000 in the test script, the script will run without a stack overflow.  On sucessful runs, malloced memory went down from ~60MB inside the module BEGIN block (at "print "after branches\n";") to ~3MB at runtime ("print "in main\n";" ) according to VMMAP (private/yellow memory).  C Stack remained at many MBs (7 to 8MB at 50000 in test script). Perl_scalarvoid, whatever it does to opcodes, should run in a loop down the optree, not recursively on every opcode and thus eating away the C stack.  I request that the above-reported bug be fixed. [Please do not change anything below this line] ----------------------------------------------------------------- --- Flags:     category=core     severity=high --- Site configuration information for perl 5.12.2: Configured by Owner at Wed Mar 23 08:05:23 2011. Summary of my perl5 (revision 5 version 12 subversion 2) configuration:      Platform:     osname=MSWin32, osvers=5.1, archname=MSWin32-x86-multi-thread     uname=''     config_args='undef'     hint=recommended, useposix=true, d_sigaction=undef     useithreads=define, usemultiplicity=define     useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef     use64bitint=undef, use64bitall=undef, uselongdouble=undef     usemymalloc=n, bincompat5005=undef   Compiler:     cc='cl', ccflags ='-nologo -GF -W3 -Od -MD -Zi -DDEBUGGING -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT  -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO',     optimize='-Od -MD -Zi -DDEBUGGING',     cppflags='-DWIN32'     ccversion='13.10.3077', gccversion='', gccosandvers=''     intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234     d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=8     ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64', lseeksize=8     alignbytes=8, prototype=define   Linker and Libraries:     ld='link', ldflags ='-nologo -nodefaultlib -debug  -libpath:"c:\perl512\lib\CORE"  -machine:x86'     libpth="c:\Program Files\Microsoft Visual Studio .NET 2003\VC7\lib"     libs=  oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib  netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib     perllibs=  oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib  netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib     libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl512.lib     gnulibc_version=''   Dynamic Linking:     dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '     cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug  -libpath:"c:\perl512\lib\CORE"  -machine:x86' Locally applied patches:     --- @INC for perl 5.12.2:     C:/perl512/site/lib     C:/perl512/lib     . --- Environment for perl 5.12.2:     HOME (unset)     LANG (unset)     LANGUAGE (unset)     LD_LIBRARY_PATH (unset)     LOGDIR (unset)     PATH=C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE;C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\BIN;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin\prerelease;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin;C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322;C:\perl512\bin;C:\sources\glibbin\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32\wbem;C:\Perl\site\bin;C:\Perl\bin;C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin;C:\cygwin\bin;     PERL_BADLANG (unset)     PERL_DEBUG_MSTATS=2     SHELL (unset)
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 215b
included pics of VS debugger and opcode structs, the pp_cond_expr and pp_null only 2 things inthe recursive pattern, also added full C stack trace, and added the test Perl script that generates these stack overflows
Download stk.pl
text/x-perl 695b
#!/usr/bin/perl -w use strict; BEGIN { my $time = time; { my $str = "BEGIN {\nmy \$i = 100000; ".'if($i == 0) {print 0;}'."\n"; for (1..100000) { $str .= 'elsif ($i == '.$_.') {print '.$_.';}'."\n"; } $str .= 'print "after branches\n"; system("pause"); } 1;'; open(FH, '>', 'testmod'.$time.'.pm') or die "Could not open ".'testmod'.$time.'.pm'.": $!"; binmode(FH); syswrite(FH,$str) or die "Could not write ".'testmod'.$time.'.pm'.": $!"; close(FH); } print "before require\n"; system("pause"); require 'testmod'.$time.'.pm'; } print "in main\n"; system("pause");
Download perlstk1.PNG
image/png 91.1k
perlstk1.PNG
Download perlstk2.png
image/png 90.9k
perlstk2.png
Download perlstackcrash.txt
text/plain 242.5k

Message body is not shown because it is too large.

RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 3.3k
On Sun Jan 15 10:35:13 2012, bulk88 wrote: Show quoted text
> > > Perl lexer (???) has a deep recursion bug in Perl_scalarvoid when > given a very large Perl subroutine to run.� Perl_scalarvoid calls > itself over and over, for what I blindly guess is every opcode in > the sub.� If there are too many opcodes, C stack overflows. > > I could not replicate this with any stock ActivePerl (AP 5.10.0, AP > 5.12.3).� While the test script is running, ActivePerls peak at 8 > MB on the C stack.� I checked with VMMAP.� If I lower the stack > reserve from 16 MB to 256KB in the PE header on perl.exe from > ActivePerls, I will get the same exact Perl_scalarvoid stack > overflow.� There is no reason for the interpreter to peak at many > MBs of C stack, which is irreversibly expanded (there are OS > specific ways to shrink C stacks.... I know it can be done with > VirtualFree and VirtualAlloc on Windows, but that is the wrong way > to fix C stack recursion) and wasted, never to be used again after > BEGIN blocks run.� I have not tested doing the "require" at > runtime.� On other perl scripts and apps I run, all the interpreter > (APs and my compiled Perl) peak at 20-50KB of C stack which is > fine.� I assume that the reason that my self-compiled Perl will > stack overflow at 16MB and ActivePerls do not is because of high C > stack overhead of each recursive Perl_scalarvoid when Perl is > compiled with -Od (no registers) meanwhile ActivePerls are compiled > with -O1 (small code). > > I wrote this test script to test how efficient Perl is at returning > memory to the OS after a Perl Module is "use"d and if, and how > well, memory behind the BEGIN blocks (SVs, CVs, Opcodes, pads, raw > malloced blocks) is returned to the OS.� If I lower the 100000 to > 50000 in the test script, the script will run without a stack > overflow.� On sucessful runs, malloced memory went down from ~60MB > inside the module BEGIN block (at "print "after branches\n";") to > ~3MB at runtime ("print "in main\n";" ) according to VMMAP > (private/yellow memory).� C Stack remained at many MBs (7 to 8MB at > 50000 in test script). > > Perl_scalarvoid, whatever it does to opcodes, should run in a loop > down the optree, not recursively on every opcode and thus eating > away the C stack.� I request that the above-reported bug be fixed. >
1. I modified the test program you wrote to take the number of iterations from the command-line rather than having it hard-coded. I then ran the program on the two OSes to which I have access, Darwin and Linux. In both cases, the program failed. $ perl 108276_stk.pl 10 number: 10 before require Can't exec "pause": No such file or directory at 108276_stk.pl line 23. 10after branches Can't exec "pause": No such file or directory at testmod1326659374.pm line 14. in main Can't exec "pause": No such file or directory at 108276_stk.pl line 27. 'pause' is not an installed executable on those platforms (though it has a man page as a C library function). Could you modify your program to avoid the use of 'pause'? That would enable more people to run it. 2. While the screenshots you posted via the RT GUI are displaying, I suspect they won't show up on the perl5-porters mailing list or newsgroup. Thank you for your report. Jim Keenan
Download 108276_stk.pl
text/x-perl 760b
#!/usr/bin/perl -w use strict; BEGIN { my $number = shift @ARGV; print "number: $number\n"; my $time = time; { my $str = "BEGIN {\nmy \$i = $number; ".'if($i == 0) {print 0;}'."\n"; for (1..$number) { $str .= 'elsif ($i == '.$_.') {print '.$_.';}'."\n"; } $str .= 'print "after branches\n"; system("pause"); } 1;'; open(FH, '>', 'testmod'.$time.'.pm') or die "Could not open ".'testmod'.$time.'.pm'.": $!"; binmode(FH); syswrite(FH,$str) or die "Could not write ".'testmod'.$time.'.pm'.": $!"; close(FH); } print "before require\n"; system("pause"); require 'testmod'.$time.'.pm'; } print "in main\n"; system("pause");
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 3.6k
On Sun Jan 15 12:58:36 2012, jkeenan wrote: Show quoted text
> On Sun Jan 15 10:35:13 2012, bulk88 wrote:
> > > > > > Perl lexer (???) has a deep recursion bug in Perl_scalarvoid when > > given a very large Perl subroutine to run.� Perl_scalarvoid calls > > itself over and over, for what I blindly guess is every opcode in > > the sub.� If there are too many opcodes, C stack overflows. > > > > I could not replicate this with any stock ActivePerl (AP 5.10.0, AP > > 5.12.3).� While the test script is running, ActivePerls peak at 8 > > MB on the C stack.� I checked with VMMAP.� If I lower the stack > > reserve from 16 MB to 256KB in the PE header on perl.exe from > > ActivePerls, I will get the same exact Perl_scalarvoid stack > > overflow.� There is no reason for the interpreter to peak at many > > MBs of C stack, which is irreversibly expanded (there are OS > > specific ways to shrink C stacks.... I know it can be done with > > VirtualFree and VirtualAlloc on Windows, but that is the wrong way > > to fix C stack recursion) and wasted, never to be used again after > > BEGIN blocks run.� I have not tested doing the "require" at > > runtime.� On other perl scripts and apps I run, all the interpreter > > (APs and my compiled Perl) peak at 20-50KB of C stack which is > > fine.� I assume that the reason that my self-compiled Perl will > > stack overflow at 16MB and ActivePerls do not is because of high C > > stack overhead of each recursive Perl_scalarvoid when Perl is > > compiled with -Od (no registers) meanwhile ActivePerls are compiled > > with -O1 (small code). > > > > I wrote this test script to test how efficient Perl is at returning > > memory to the OS after a Perl Module is "use"d and if, and how > > well, memory behind the BEGIN blocks (SVs, CVs, Opcodes, pads, raw > > malloced blocks) is returned to the OS.� If I lower the 100000 to > > 50000 in the test script, the script will run without a stack > > overflow.� On sucessful runs, malloced memory went down from ~60MB > > inside the module BEGIN block (at "print "after branches\n";") to > > ~3MB at runtime ("print "in main\n";" ) according to VMMAP > > (private/yellow memory).� C Stack remained at many MBs (7 to 8MB at > > 50000 in test script). > > > > Perl_scalarvoid, whatever it does to opcodes, should run in a loop > > down the optree, not recursively on every opcode and thus eating > > away the C stack.� I request that the above-reported bug be fixed. > >
> > 1. I modified the test program you wrote to take the number of > iterations from the command-line rather than having it hard-coded. I > then ran the program on the two OSes to which I have access, Darwin and > Linux. In both cases, the program failed. > > $ perl 108276_stk.pl 10 > number: 10 > before require > Can't exec "pause": No such file or directory at 108276_stk.pl line 23. > 10after branches > Can't exec "pause": No such file or directory at testmod1326659374.pm > line 14. > in main > Can't exec "pause": No such file or directory at 108276_stk.pl line 27. > > 'pause' is not an installed executable on those platforms (though it has > a man page as a C library function). > > Could you modify your program to avoid the use of 'pause'? That would > enable more people to run it.
I haven’t used Windows for a long, long time (except IE for web testing), but if I remember correctly the pause command prints ‘Press the "any" key to continue...’ and waits for a keystroke before exiting. Changing system("pause") to: system("perl -e '$|=1; print q|Press return to continue... |; <>'") should work. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 779b
On Sun Jan 15 13:16:04 2012, sprout wrote: Show quoted text
> I haven’t used Windows for a long, long time (except IE for web > testing), but if I remember correctly the pause command prints ‘Press > the "any" key to continue...’ and waits for a keystroke before exiting. > > Changing system("pause") to: > > system("perl -e '$|=1; print q|Press return to continue... |; <>'") > > should work. >
Google says "pause" equivalent on POSIX is "echo -n "Press any key to continue . . ." && read -n 1". The system("pause") lines are the points I suggest to look at memory usage of the Perl process. Not sure if there are any tools that can show reserved size of stack vs allocated amount of stack in virtual memory system on Linux/Unix. I used VMMAP for Windows to get the memory counts.
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Mon, 16 Jan 2012 11:50:22 +0000
To: perl5-porters [...] perl.org
From: Dave Mitchell <davem [...] iabyn.com>
Download (untitled) / with headers
text/plain 832b
On Sun, Jan 15, 2012 at 10:35:14AM -0800, bulk 88 wrote: The code can be simplified to the following: my $n = $ARGV[0]; die unless $n =~ /^\d+$/; my $code = 'my $i = 0; if ($i) { print }' . "\n"; $code .= 'elsif ($i) { print }' . "\n" for 1..$n; eval $code; segfaults for me on blead with n >= about 5000. In blead, it's recursing in S_finalize_op rather than scalarvoid; not sure whether this is instead of or in addition to a scalarvoid problem. -- "But Sidley Park is already a picture, and a most amiable picture too. The slopes are green and gentle. The trees are companionably grouped at intervals that show them to advantage. The rill is a serpentine ribbon unwound from the lake peaceably contained by meadows on which the right amount of sheep are tastefully arranged." -- Lady Croom, "Arcadia"
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 957b
On Mon Jan 16 03:51:55 2012, davem wrote: Show quoted text
> On Sun, Jan 15, 2012 at 10:35:14AM -0800, bulk 88 wrote: > > The code can be simplified to the following: > > my $n = $ARGV[0]; > die unless $n =~ /^\d+$/; > > my $code = 'my $i = 0; if ($i) { print }' . "\n"; > $code .= 'elsif ($i) { print }' . "\n" for 1..$n; > eval $code; > > segfaults for me on blead with n >= about 5000. > > In blead, it's recursing in S_finalize_op rather than scalarvoid; not sure > whether this is instead of or in addition to a scalarvoid problem. >
Without actually looking, I suspect it is in addition. As I’m sure you already know, each elsif is nested inside the previous one in the op tree. So it looks as though at least S_finalize_op needs to be made iterative, and probably scalarvoid, too. And this results in a crash in op_free: perl -e'eval "sub{".q"$a+"x shift . "}"' 500000 What else needs to be made iterative? -- Father Chrysostomos
Download (untitled) / with headers
text/plain 628b
On Fri Jan 20 09:38:48 2012, sprout wrote: Show quoted text
> So it looks as though at least S_finalize_op needs to be made iterative, > and probably scalarvoid, too. > > And this results in a crash in op_free: > > perl -e'eval "sub{".q"$a+"x shift . "}"' 500000 > > What else needs to be made iterative? >
I decided to run Perl's test suite on my c stack reduced perl. First one found is on parset.t, there are many more on my list to analyze, I see one in comp/proto.t that I am working on getting a stack trace of right now. Perl_peep, when running cop_line 111 unsigned long + cop_file 0x018332bc "C:\perl-5.12.2\t\comp\parser.t"
Download plstk1.txt
text/plain 9.4k
> perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845b44) Line 8479 + 0x3 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845af8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845a58) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018459b8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845918) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845878) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018457d8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845738) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845698) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018455f8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845558) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018454b8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845418) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845378) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018452d8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845238) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845198) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018450f8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01845058) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844fb8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844f18) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844e78) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844dd8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844d38) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844c98) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844bf8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844b58) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844ab8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844a18) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844978) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018448d8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848e88) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848de8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848d48) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848ca8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848c08) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848b68) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848ac8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848a28) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848988) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018488e8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848848) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018487a8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848708) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848668) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018485c8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848528) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848488) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018483e8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848348) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018482a8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848208) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848168) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018480c8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848028) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847f88) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847ee8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847e48) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847da8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847d08) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847c68) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847bc8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847b28) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847a88) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018479e8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847948) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018478a8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847808) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847768) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018476c8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847628) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847588) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018474e8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847448) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018473a8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847308) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847268) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018471c8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847128) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847088) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01846fe8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01846f48) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018549f8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01854958) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018548b8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01854818) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01854778) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018546d8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01854638) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01854598) Line 8729 + 0x13 C perl512.dll!Perl_newPROG(interpreter * my_perl=0x0035403c, op * o=0x01837a60) Line 2365 + 0x17 C perl512.dll!Perl_yyparse(interpreter * my_perl=0x0035403c) Line 143 + 0x2c C perl512.dll!S_parse_body(interpreter * my_perl=0x0035403c, char * * env=0x002428f8, void (interpreter *)* xsinit=0x281d2260) Line 2160 + 0x9 C perl512.dll!perl_parse(interpreter * my_perl=0x0035403c, void (interpreter *)* xsinit=0x281d2260, int argc=0x00000002, char * * argv=0x00242510, char * * env=0x002428f8) Line 1605 + 0x11 C perl512.dll!RunPerl(int argc=0x00000002, char * * argv=0x00242510, char * * env=0x002428f8) Line 263 + 0x1a C++ perl.exe!main(int argc=0x00000002, char * * argv=0x00242510, char * * env=0x00242d48) Line 73 + 0x12 C perl.exe!mainCRTStartup() Line 398 + 0xe C kernel32.dll!_BaseProcessStart@4() + 0x23
Download (untitled) / with headers
text/plain 1.1k
/t/cmd/for.t Overflow in Peep at cop_line 462 unsigned long + cop_file 0x0186ed8c "C:\perl-5.12.2\t\cmd\for.t" char * /t/io/fs.t overflow in peep at cop_line 416 unsigned long + cop_file 0x0193b074 "C:\perl-5.12.2\t\io\fs.t" char * overflow in peep at /t/re/pat_advanced.t cop_line 832 unsigned long + cop_file 0x01add1b4 "C:\perl-5.12.2\t\re\pat_advanced.t" char * half the re folder failed at 28KB stack size, im not going to analyze them unless someone wants me to, i guess they are all peeps /t/op/pack.t overflow in S_group_end, this is interesting, i set stack to 81920 bytes long, not 28KB, at 28KB this overflowed in peek cop_line 1230 unsigned long + cop_file 0x01bc671c "C:\perl-5.12.2\t\op\pack.t" char * I killed "perl harness " when it started running cpan folder tests. I also include the way I change the c stack size for these tests. I modified perlmain.c . PLSTK is the number of pages you want the c stack to be long. I wrote the code for 32 bit windows only. If someone wants me to try something specific, reply to the bug, I have no other ideas for figuring out what has bad C stack recursion in perl.
> perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01adb7e8) Line 8479 + 0x3 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01adb770) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01adb9bc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01adbc08) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01adb108) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01adc0b0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01adc8c8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad8540) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad8d1c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01adbfa4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad98a0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad5294) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad5e90) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad604c) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad5c1c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad5b10) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad6728) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad1e54) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad22a4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad6f70) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad30dc) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad3864) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ace47c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01acee48) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac6c84) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac6498) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ad2fd0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac6e30) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac3930) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac4a0c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac48ac) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abf6cc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abf988) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abfc44) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abff00) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac01bc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac05dc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac0844) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac0b00) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac47a0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac1154) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac1200) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abd050) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abd0fc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abd460) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abd50c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abd870) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abd91c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abdc80) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abdd2c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abe090) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abe13c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ac1064) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abbf30) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ab09e4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ab0ca0) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ab0f5c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ab1218) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ab14d4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01abbab0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ab1938) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01ab23ec) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0196d34c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01909480) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01909a9c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01909db4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018f4ebc) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018f93c4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018f5450) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e93d4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018f5960) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e9670) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e9720) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e9b4c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e9bfc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018ea028) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018ea354) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018ea680) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e19e8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e18a4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e1c14) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e1e40) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e206c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e2298) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e24c4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e26f0) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e291c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e2b48) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e2d74) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e2fa0) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e31cc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e33f8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e3624) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018dcf98) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018e9580) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018dd2e0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018ddb14) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018ddfe4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018dee10) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018ded70) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d9e10) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d9d04) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018da30c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018da59c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018da82c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018daabc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018dacf8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018da21c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d4570) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d482c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d4ae8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d4da4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d5060) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d531c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d55d8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d5894) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d4480) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d5cd4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d5bc8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d288c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d2cd4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d3788) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d3c74) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d0368) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d05b0) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d0cb0) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d3bd8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d12e8) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d2038) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018d10fc) Line 8729 + 0x13 C perl512.dll!Perl_newATTRSUB(interpreter * my_perl=0x0035403c, long floor=25, op * o=0x018cb22c, op * proto=0x00000000, op * attrs=0x00000000, op * block=0x018d1088) Line 5891 + 0x16 C perl512.dll!Perl_yyparse(interpreter * my_perl=0x0035403c) Line 567 + 0x2b C perl512.dll!S_parse_body(interpreter * my_perl=0x0035403c, char * * env=0x00242900, void (interpreter *)* xsinit=0x281d2260) Line 2160 + 0x9 C perl512.dll!perl_parse(interpreter * my_perl=0x0035403c, void (interpreter *)* xsinit=0x281d2260, int argc=2, char * * argv=0x00242510, char * * env=0x00242900) Line 1605 + 0x11 C perl512.dll!RunPerl(int argc=2, char * * argv=0x00242510, char * * env=0x00242900) Line 263 + 0x1a C++ perl.exe!main(int argc=2, char * * argv=0x00242510, char * * env=0x00242d48) Line 85 + 0x12 C perl.exe!mainCRTStartup() Line 398 + 0xe C kernel32.dll!_BaseProcessStart@4() + 0x23
Download perlmain.c
text/x-csrc 3.3k
#include "EXTERN.h" #include "perl.h" #define _WIN32_WINNT 0x0400 #include <windows.h> #ifdef __GNUC__ /* Mingw32 defaults to globing command line * This is inconsistent with other Win32 ports and * seems to cause trouble with passing -DXSVERSION=\"1.6\" * So we turn it off like this, but only when compiling * perlmain.c: perlmainst.c is linked into the same executable * as win32.c, which also does this, so we mustn't do it twice * otherwise we get a multiple definition error. */ #ifndef PERLDLL int _CRT_glob = 0; #endif #endif DWORD FilterFunction(LPEXCEPTION_POINTERS exceptionPtr) { printf("1 "); // printed first return EXCEPTION_EXECUTE_HANDLER; } int main(int argc, char **argv, char **env) { char * stackSizeEnv = getenv("PLSTK"); int newStackSize = 0; DWORD oldProtect; PBYTE pPtr; MEMORY_BASIC_INFORMATION infoRes; MEMORY_BASIC_INFORMATION infoGuard; MEMORY_BASIC_INFORMATION infoAlloc; DWORD_PTR stackEnd; DWORD_PTR stackAllocBegin; BOOL ret; __asm mov pPtr, esp if(stackSizeEnv) { newStackSize = atoi(stackSizeEnv); } else { newStackSize = 7; } if(newStackSize) { assert(VirtualQuery(pPtr, &infoRes, sizeof(MEMORY_BASIC_INFORMATION))); assert(VirtualQuery((DWORD_PTR)infoRes.AllocationBase, &infoRes, sizeof(MEMORY_BASIC_INFORMATION))); assert(VirtualQuery((DWORD_PTR)infoRes.AllocationBase+infoRes.RegionSize, &infoGuard, sizeof(MEMORY_BASIC_INFORMATION))); assert(VirtualQuery((DWORD_PTR)infoRes.AllocationBase+infoRes.RegionSize +infoGuard.RegionSize, &infoAlloc, sizeof(MEMORY_BASIC_INFORMATION))); stackEnd = (DWORD_PTR)infoRes.AllocationBase+infoRes.RegionSize +infoGuard.RegionSize+infoAlloc.RegionSize; stackAllocBegin = stackEnd-(newStackSize*4096); ret = VirtualAlloc(stackAllocBegin, (newStackSize*4096), MEM_COMMIT, PAGE_READWRITE); //ret = VirtualProtect(stackAllocBegin, (newStackSize*4096), // PAGE_READWRITE, &oldProtect); //printf("vp ret=%u glr=%u\n", ret, GetLastError()); ret = VirtualAlloc(stackAllocBegin-(4096*2), (4096*2), MEM_COMMIT, PAGE_NOACCESS); //printf("vp ret=%u glr=%u\n", ret, GetLastError()); //ret = VirtualProtect(stackEnd-(newStackSize*4096)-4096, 4096, // PAGE_NOACCESS, &oldProtect); //printf("vp ret=%u glr=%u\n", ret, GetLastError()); //while( ! (stMemBasicInfo.Protect & PAGE_GUARD)) { // assert(VirtualQuery((DWORD_PTR)stMemBasicInfo.BaseAddress-1, &stMemBasicInfo, // sizeof(stMemBasicInfo))); //} //assert(VirtualProtect(stMemBasicInfo.BaseAddress, stMemBasicInfo.RegionSize, // PAGE_NOACCESS, &oldProtect)); //assert(VirtualQuery((DWORD_PTR)stMemBasicInfo.BaseAddress-1, &stMemBasicInfo, // sizeof(stMemBasicInfo))); //assert(VirtualFree((DWORD_PTR)stMemBasicInfo.AllocationBase, // 0, MEM_RELEASE)); } if(0) { exit(1); } __try { ret = RunPerl(argc, argv, env); } __except(FilterFunction(GetExceptionInformation())) { ret = 1; } return ret; }
Download io.fs.t.stk.txt
text/plain 9.9k
ntdll.dll!_RtlFreeHeap@12() + 0x1763f msvcrt.dll!_free() + 0xc3 perl512.dll!VMem::Free(void * pMem=0x0193ae34) Line 229 + 0xa C++ perl512.dll!CPerlHost::Free(void * ptr=0x0193ae34) Line 68 + 0x22 C++ perl512.dll!PerlMemFree(IPerlMem * piPerl=0x00245b6c, void * ptr=0x0193ae34) Line 311 C++ perl512.dll!Perl_safesysfree(void * where=0x0193ae34) Line 262 + 0x1a C perl512.dll!Perl_sv_clear(interpreter * my_perl=0x0035403c, sv * const sv=0x0192e964) Line 5865 + 0xc C perl512.dll!Perl_sv_free2(interpreter * my_perl=0x0035403c, sv * const sv=0x0192e964) Line 5985 + 0xd C perl512.dll!Perl_sv_free(interpreter * my_perl=0x0035403c, sv * const sv=0x0192e964) Line 5962 + 0xd C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0193a14c) Line 8784 + 0xd C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019396a8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0193a75c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0193a660) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0193aae0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019353d4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01935988) Line 8671 + 0x13 C > perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0193588c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01936014) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0193a3b4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01936364) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019362bc) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019366e8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01931d78) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019322c4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019328f8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0193a314) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01932e94) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192bb9c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192bdac) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192bde8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01933290) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192c040) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192cbc8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192cd34) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192cdac) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192c7bc) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019255b8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01925630) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01924fdc) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01926520) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01921530) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019215a8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01926b60) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01921c48) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01921cc0) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019217ac) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019222a0) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01922318) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01921ec4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01922818) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019225bc) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01922f2c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01922c98) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191b45c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191b4d4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0192251c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191c304) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191c054) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191c940) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191c6e4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01918140) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01917ee4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191851c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191b6d8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019188bc) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01918930) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01918ea4) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191902c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01918b84) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019194a8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019192a4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01914e58) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01918ae4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019152b8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01915540) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0191594c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01915988) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01915a38) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019156ec) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01915d1c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01916048) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01916b28) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019105b8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019107b0) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019107ec) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01910a5c) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01910c94) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01910bec) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01910f38) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01911170) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01911318) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019113c8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01911478) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01911528) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x019115d8) Line 8671 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01911948) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01911dd0) Line 8671 + 0x13 C perl512.dll!Perl_newPROG(interpreter * my_perl=0x0035403c, op * o=0x01911ed8) Line 2365 + 0x17 C perl512.dll!Perl_yyparse(interpreter * my_perl=0x0035403c) Line 143 + 0x2c C perl512.dll!S_parse_body(interpreter * my_perl=0x0035403c, char * * env=0x002428f0, void (interpreter *)* xsinit=0x281d2260) Line 2160 + 0x9 C perl512.dll!perl_parse(interpreter * my_perl=0x0035403c, void (interpreter *)* xsinit=0x281d2260, int argc=2, char * * argv=0x00242510, char * * env=0x002428f0) Line 1605 + 0x11 C perl512.dll!RunPerl(int argc=2, char * * argv=0x00242510, char * * env=0x002428f0) Line 263 + 0x1a C++ perl.exe!main(int argc=2, char * * argv=0x00242510, char * * env=0x00242d48) Line 85 + 0x12 C perl.exe!mainCRTStartup() Line 398 + 0xe C kernel32.dll!_BaseProcessStart@4() + 0x23
Download for.t.stk.txt
text/plain 9.4k
> perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186e564) Line 8479 + 0x3 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186e48c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186e9c0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01869dc4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186a3c8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186aa74) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186b104) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186b694) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01866864) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01866e68) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186746c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01867b18) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018681a8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01862648) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01862bbc) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018631a4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0186378c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01863e1c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185f23c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185f7b0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185fd08) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018602f0) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018608d8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01860f68) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185c368) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185c8dc) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185ce34) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185d41c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185da04) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185759c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01857c10) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01858184) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018586dc) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01858cc4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018592ac) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01854958) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01854fcc) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01855540) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01855a98) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0185602c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018520a8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01852700) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01852d3c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01853278) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01853798) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01853d40) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184d384) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184d9d4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184e008) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184e53c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184ea54) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01849280) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018497d4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01849dec) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184a3e8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184a8e4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184adc4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184645c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01846a28) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184709c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018476f4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01847c4c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01848188) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184325c) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018437d4) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01843e10) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844430) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01844950) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183f334) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183f514) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183f198) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183fe08) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018400a8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0184051c) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x018406c8) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183a384) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183a530) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183aaa4) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183ad30) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183afbc) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183b658) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183b95c) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x0183bd58) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01835b84) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01835e8c) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01836264) Line 8729 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01836718) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01836a30) Line 8735 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01836e00) Line 8722 + 0x13 C perl512.dll!Perl_peep(interpreter * my_perl=0x0035403c, op * o=0x01837700) Line 8729 + 0x13 C perl512.dll!Perl_newPROG(interpreter * my_perl=0x0035403c, op * o=0x01837a18) Line 2365 + 0x17 C perl512.dll!Perl_yyparse(interpreter * my_perl=0x0035403c) Line 143 + 0x2c C perl512.dll!S_parse_body(interpreter * my_perl=0x0035403c, char * * env=0x002428f8, void (interpreter *)* xsinit=0x281d2260) Line 2160 + 0x9 C perl512.dll!perl_parse(interpreter * my_perl=0x0035403c, void (interpreter *)* xsinit=0x281d2260, int argc=2, char * * argv=0x00242510, char * * env=0x002428f8) Line 1605 + 0x11 C perl512.dll!RunPerl(int argc=2, char * * argv=0x00242510, char * * env=0x002428f8) Line 263 + 0x1a C++ perl.exe!main(int argc=2, char * * argv=0x00242510, char * * env=0x00242d48) Line 85 + 0x12 C perl.exe!mainCRTStartup() Line 398 + 0xe C kernel32.dll!_BaseProcessStart@4() + 0x23
RT-Send-CC: perl5-porters [...] perl.org
Subject: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Wed, 17 Jul 2013 23:28:48 +0200
To: perl5-porters [...] perl.org, perlbug-followup [...] perl.org
From: Niels Thykier <niels [...] thykier.net>
Download (untitled) / with headers
text/plain 1.5k
Hi, I cannot reproduce the issue in S_finalize_op on blead[1]. It is possible that it has been "fixed" somehow (or we got different architectures). On the other hand, I can reproduce the crash caused by: perl -e'eval "sub{".q"$a+"x shift . "}"' 500000 I have attached a prototype patch that solves the problem (at least for me). With the patch applied, I can run it with up to at least 2M without it crashing - I have not tested beyond that because perl starts to use >= 4GB of RAM around the 2M mark. A more memory friendly test case is definitely welcome. :) For the reviewer(s): the patch is much easier to read by ignoring space changes[2]. It re-uses the basic principe of the DEFER marco used in the peephole optimizer. The "major" difference is that it uses a fixed-size stack rather than a fixed-size queue. The size of the queue did not seem to matter a lot (even with MAX_DEFERRED reduced to 2 was the crash avoided in original test case). The test suite showed no regression, perl was configured with: ./Configure -des -Dusedevel ~Niels [1] I have been using code suggested by Dave Mitchell (rewritten as a perl one-liner) ./perl -e 'my $code = q[my $i = 0; if ($i) { print } ] . "\n";' -e '$code .= q[ elsif ($i) { print } ] . "\n" for 1..$ARGV[0];' -e 'eval $code' 10000 [2] Compare $ git diff --ignore-all-space --stat op.c | 37 [...] 1 file changed, 34 insertions(+), 3 deletions(-) versus. $ git diff --stat op.c | 141 [...] 1 file changed, 86 insertions(+), 55 deletions(-)

Message body is not shown because sender requested not to inline it.

Download (untitled) / with headers
text/plain 997b
On Wed Jul 17 14:29:33 2013, niels@thykier.net wrote: Show quoted text
> Hi, > > I cannot reproduce the issue in S_finalize_op on blead[1]. It is > possible that it has been "fixed" somehow (or we got different > architectures). > > On the other hand, I can reproduce the crash caused by: > > perl -e'eval "sub{".q"$a+"x shift . "}"' 500000 >
I'll update this ticket for 5.19.2. All experiments were done with a intentionally C stack reduced perl, the C stack is fixed at 20 KB, the perl is -O1, so the parameters in the callstacks may be/are garbage. Perl_scalarvoid on stk.pl script above is still a problem. I attach a new callstack. The davem script above is still a problem. New callstack attached. The Father C rep operator on add operator then eval is still a problem. Callstack attached. I also attach a newer perlmain.c that I used to reduce the C stack's size, the original c stack shrinking code above was more hackish and only worked on DEBUGGING perl. -- bulk88 ~ bulk88 at hotmail.com

Message body is not shown because it is too large.

Download perlmain.c
text/x-csrc 3.3k
#include "EXTERN.h" #include "perl.h" #ifdef __GNUC__ /* Mingw32 defaults to globing command line * This is inconsistent with other Win32 ports and * seems to cause trouble with passing -DXSVERSION=\"1.6\" * So we turn it off like this, but only when compiling * perlmain.c: perlmainst.c is linked into the same executable * as win32.c, which also does this, so we mustn't do it twice * otherwise we get a multiple definition error. */ #ifndef PERLDLL int _CRT_glob = 0; #endif #endif DWORD FilterFunction(LPEXCEPTION_POINTERS exceptionPtr) { printf("1 "); // printed first return EXCEPTION_EXECUTE_HANDLER; } int main(int argc, char **argv, char **env) { char * stackSizeEnv = getenv("PLSTK"); int newStackSize = 0; DWORD oldProtect; PBYTE pPtr; MEMORY_BASIC_INFORMATION infoRes; MEMORY_BASIC_INFORMATION infoGuard; MEMORY_BASIC_INFORMATION infoAlloc; DWORD_PTR stackEnd; DWORD_PTR stackAllocBegin; BOOL ret; __asm mov pPtr, esp if(stackSizeEnv) { newStackSize = atoi(stackSizeEnv); } else { newStackSize = 5; } if(newStackSize) { ret = VirtualQuery(pPtr, &infoRes, sizeof(MEMORY_BASIC_INFORMATION)); assert(ret); ret = VirtualQuery((DWORD_PTR)infoRes.AllocationBase, &infoRes, sizeof(MEMORY_BASIC_INFORMATION)); assert(ret); ret = VirtualQuery((DWORD_PTR)infoRes.AllocationBase+infoRes.RegionSize, &infoGuard, sizeof(MEMORY_BASIC_INFORMATION)); assert(ret); ret = VirtualQuery((DWORD_PTR)infoRes.AllocationBase +infoRes.RegionSize +infoGuard.RegionSize ,&infoAlloc, sizeof(MEMORY_BASIC_INFORMATION)); assert(ret); stackEnd = (DWORD_PTR)infoRes.AllocationBase+infoRes.RegionSize +infoGuard.RegionSize+infoAlloc.RegionSize; stackAllocBegin = stackEnd-(newStackSize*4096); ret = VirtualAlloc(stackAllocBegin, (newStackSize*4096), MEM_COMMIT, PAGE_READWRITE); //ret = VirtualProtect(stackAllocBegin, (newStackSize*4096), // PAGE_READWRITE, &oldProtect); printf("vp ret=%u glr=%u\n", ret, GetLastError()); ret = VirtualAlloc(stackAllocBegin-(4096*2), (4096*2), MEM_COMMIT, PAGE_NOACCESS); printf("vp ret=%u glr=%u\n", ret, GetLastError()); //ret = VirtualProtect(stackEnd-(newStackSize*4096)-4096, 4096, // PAGE_NOACCESS, &oldProtect); //printf("vp ret=%u glr=%u\n", ret, GetLastError()); //while( ! (stMemBasicInfo.Protect & PAGE_GUARD)) { // assert(VirtualQuery((DWORD_PTR)stMemBasicInfo.BaseAddress-1, &stMemBasicInfo, // sizeof(stMemBasicInfo))); //} //assert(VirtualProtect(stMemBasicInfo.BaseAddress, stMemBasicInfo.RegionSize, // PAGE_NOACCESS, &oldProtect)); //assert(VirtualQuery((DWORD_PTR)stMemBasicInfo.BaseAddress-1, &stMemBasicInfo, // sizeof(stMemBasicInfo))); //assert(VirtualFree((DWORD_PTR)stMemBasicInfo.AllocationBase, // 0, MEM_RELEASE)); } if(0) { exit(1); } __try { ret = RunPerl(argc, argv, env); } __except(FilterFunction(GetExceptionInformation())) { ret = 1; } return ret; }

Message body is not shown because it is too large.

RT-Send-CC: perl5-porters [...] perl.org
RT web interface lost the attachment. Adding a missing one. -- bulk88 ~ bulk88 at hotmail.com
Download (untitled) / with headers
text/plain 192b
On Wed Jul 17 19:10:02 2013, bulk88 wrote: Show quoted text
> RT web interface lost the attachment. Adding a missing one.
Ok, I uploaded a 0 byte file before. Trying again. -- bulk88 ~ bulk88 at hotmail.com

Message body is not shown because it is too large.

RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.3k
On Wed Jul 17 14:29:33 2013, niels@thykier.net wrote: Show quoted text
> Hi, > > I cannot reproduce the issue in S_finalize_op on blead[1]. It is > possible that it has been "fixed" somehow (or we got different > architectures). > > On the other hand, I can reproduce the crash caused by: > > perl -e'eval "sub{".q"$a+"x shift . "}"' 500000 > > > I have attached a prototype patch that solves the problem (at least for > me). With the patch applied, I can run it with up to at least 2M > without it crashing - I have not tested beyond that because perl starts > to use >= 4GB of RAM around the 2M mark. > A more memory friendly test case is definitely welcome. :) > > For the reviewer(s): the patch is much easier to read by ignoring space > changes[2]. It re-uses the basic principe of the DEFER marco used in > the peephole optimizer. The "major" difference is that it uses a > fixed-size stack rather than a fixed-size queue. The size of the queue > did not seem to matter a lot (even with MAX_DEFERRED reduced to 2 was > the crash avoided in original test case). >
Applied patch, used on 20 KB C stack perl described above, -e "eval \"sub{\".q\"$a+\"x shift . \"}\"" 500000 after patch didn't crash, previously was crashing as described in earlier post of mine in this ticket. I have no comment on the correctness of this patch. -- bulk88 ~ bulk88 at hotmail.com
CC: perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Thu, 18 Jul 2013 13:12:44 +0200
To: Niels Thykier <niels [...] thykier.net>
From: Leon Timmermans <fawaka [...] gmail.com>
Download (untitled) / with headers
text/plain 372b
On Wed, Jul 17, 2013 at 11:28 PM, Niels Thykier <niels@thykier.net> wrote: Show quoted text
> For the reviewer(s): the patch is much easier to read by ignoring space > changes[2].
Then why did you post it with space changes? Not only does it deter reviewers from looking at this, it's also wrong (our style standard is crap, but it's generally considered too late to change that). Leon
CC: perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Thu, 18 Jul 2013 13:19:05 +0200
From: Niels Thykier <niels [...] thykier.net>
Download (untitled) / with headers
text/plain 988b
On 2013-07-18 13:12, Leon Timmermans wrote: Show quoted text
> On Wed, Jul 17, 2013 at 11:28 PM, Niels Thykier <niels@thykier.net> wrote:
>> For the reviewer(s): the patch is much easier to read by ignoring space >> changes[2].
> > Then why did you post it with space changes? Not only does it deter > reviewers from looking at this, it's also wrong (our style standard is > crap, but it's generally considered too late to change that). > > Leon >
The space changes are caused by adding an extra scope, i.e. code became while (something) { code-with-minor-modifications } I can rewrite the patch as while (something) { code-with-minor-modifications } but I suspected that it would make things worse in the long-term. In regards to the spaces used. As I understood it, the "desired" intention is " ", "\t", "\t ", "\t\t". So that is what I have been using so far. If it is wrong, then by all means do correct me so I don't include it in future patches. ~Niels
CC: perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Thu, 18 Jul 2013 12:27:46 +0100
To: Niels Thykier <niels [...] thykier.net>
From: Nicholas Clark <nick [...] ccl4.org>
Download (untitled) / with headers
text/plain 2.1k
On Thu, Jul 18, 2013 at 01:19:05PM +0200, Niels Thykier wrote: Show quoted text
> On 2013-07-18 13:12, Leon Timmermans wrote:
> > On Wed, Jul 17, 2013 at 11:28 PM, Niels Thykier <niels@thykier.net> wrote:
> >> For the reviewer(s): the patch is much easier to read by ignoring space > >> changes[2].
> > > > Then why did you post it with space changes? Not only does it deter > > reviewers from looking at this, it's also wrong (our style standard is > > crap, but it's generally considered too late to change that). > > > > Leon > >
> > The space changes are caused by adding an extra scope, i.e. > > code > > became > > while (something) > { > code-with-minor-modifications > } > > I can rewrite the patch as > > while (something) > { > code-with-minor-modifications > } > > but I suspected that it would make things worse in the long-term.
Yes, typically we have been re-indenting when adding scopes. So you're right that the answer isn't as obvious as it first seemed. In this case, I think for ease of review the best course of action would have been to attach the "proper" diff and put a whitespace-ignoring diff inline in your message. (Because I'm unaware of any means for a reviewer to generate that diff without having to 1) checkout the correct parent version 2) apply your patch 3) run diff themselves whereas you are in a position to do just step 3, and save anyone else having to quit their e-mail client to duplicate work) Show quoted text
> In regards to the spaces used. As I understood it, the "desired" > intention is " ", "\t", "\t ", "\t\t". So that is what I have > been using so far. If it is wrong, then by all means do correct me so I > don't include it in future patches.
There's an editor block at the bottom of each file which is supposed to get (at least) emacs and vi to indent at 4 columns, and expand tabs to spaces. Historically most of the code has hard tabs, and the alignment mostly seems to assume a tabstop is at 8 spaces, but the rough plan is to eliminate tabs on any line that gets changed for any other reason. The intent is to avoid the "blame" history of files (at least of the complex old C code) being confused by having whitespace only changes. Nicholas Clark
CC: Niels Thykier <niels [...] thykier.net>, perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Thu, 18 Jul 2013 15:13:35 +0100
To: Nicholas Clark <nick [...] ccl4.org>
From: Dave Mitchell <davem [...] iabyn.com>
Download (untitled) / with headers
text/plain 641b
On Thu, Jul 18, 2013 at 12:27:46PM +0100, Nicholas Clark wrote: Show quoted text
> Yes, typically we have been re-indenting when adding scopes. So you're right > that the answer isn't as obvious as it first seemed. > > In this case, I think for ease of review the best course of action would > have been to attach the "proper" diff and put a whitespace-ignoring diff > inline in your message.
My personal preference is to do it as two commits; the first adds the extra scope and the code changes; the second does just the re-indenting. -- I don't want to achieve immortality through my work... I want to achieve it through not dying. -- Woody Allen
CC: perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Thu, 18 Jul 2013 15:49:10 +0100
To: Niels Thykier <niels [...] thykier.net>
From: Dave Mitchell <davem [...] iabyn.com>
Download (untitled) / with headers
text/plain 3.5k
On Wed, Jul 17, 2013 at 11:28:48PM +0200, Niels Thykier wrote: Show quoted text
> I have attached a prototype patch that solves the problem (at least for > me). With the patch applied, I can run it with up to at least 2M > without it crashing - I have not tested beyond that because perl starts > to use >= 4GB of RAM around the 2M mark.
Some general thoughts and comments about this issue. There are several places in op.c that recursively do a partial or full treewalk of the subtree associated with a node. A quick scan of op.c for likely recursive functions turns up: Perl_op_free S_find_and_forget_pmops Perl_scalar Perl_scalarvoid Perl_list S_finalize_op Perl_doref S_my_kid S_aassign_common_vars (Then of course there's Perl_rpeep, which doesn't recursively walk the tree, but instead follows op_next nodes, recursively scanning whenever there's a branch, such as a LOGOP with an op_other field). Now, it's quite simple (especially with machine-generated code) to create an optree that's arbitrarily deep. For example: my $line = "\$cond ? \$a : \n"; my $code = ($line x 10000) . "\$b;\n"; eval $code; This creates a 10,000 depth tree. Any function which walks the tree recursively (or which uses a small fixed stack to avoid some recursion) is going to crash on a suitably pathological piece of code. Which leads me to speculate... The problem really is that there is no pointer back from the kids to the parent op. Thus to walk the tree you need a stack (C or otherwise) to record your current op_sibling iterator for every depth in the tree. If hypothetically the last kid in an op_sibling chain had a pointer back to its parent, e.g. parent | kid1 --> kid2 ---> kid3 ---> NULL | kid4 ---> kid5 --> kid6 ---> NULL becomes parent <----------------- | \ kid1 --> kid2 ---> kid3 -/ | ^ | \ | -------------------- | \ kid4 ---> kid5 --> kid6 -/ Then walking the whole subtree can be done simply by iteratively following (op_first || op_sibling) until we arrive back at the original node. For this to work, we need a temporary 'already processed' flag on ops to show that they've already been visited (so in the above when we arrive back at kid2 we know to follow op_sibling rather than op_first). Perhaps op_opt will suffice?. Also, we need to temporarily set the op_sibling of the last kid from NULL to instead point back at its parent; we revert this to NULL once we visit the kid in question (which may involve needing another flag bit). Actually, if we know we're at the last op_sibling and so the next op will be the parent, then we don't need an 'already processed' flag: we know that the next node has already been done. Or maybe the tmp pointer should point to parent->op_sibling rather than to parent, also avoiding the need for an 'already processed' flag. Of course this is all predicated on the actions being performed for each tree node not choking on the fake extra pointer on the last kid. I don't know whether this would be an issue. I had a brief attempt to see if I could get a proof-of-concept implementation to work with op_free, but that turns out to be a bit complicated by the fact that some actions are performed before the kids are walked, and some after (and of course the op itself gets freed). So I gave up as I haven't got time to look into this deeply at the moment. So I thought I'd throw it into the ring instead. -- If life gives you lemons, you'll probably develop a citric acid allergy.
CC: Nicholas Clark <nick [...] ccl4.org>, Niels Thykier <niels [...] thykier.net>, perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Thu, 18 Jul 2013 08:57:28 -0600
To: Dave Mitchell <davem [...] iabyn.com>
From: Karl Williamson <public [...] khwilliamson.com>
Download (untitled) / with headers
text/plain 654b
On 07/18/2013 08:13 AM, Dave Mitchell wrote: Show quoted text
> On Thu, Jul 18, 2013 at 12:27:46PM +0100, Nicholas Clark wrote:
>> Yes, typically we have been re-indenting when adding scopes. So you're right >> that the answer isn't as obvious as it first seemed. >> >> In this case, I think for ease of review the best course of action would >> have been to attach the "proper" diff and put a whitespace-ignoring diff >> inline in your message.
> > My personal preference is to do it as two commits; the first adds the > extra scope and the code changes; the second does just the re-indenting. >
I thought in fact, that this was the officially sanctioned thing to do.
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 4.3k
On Thu Jul 18 07:50:32 2013, davem wrote:> Some general thoughts and comments about this issue. Show quoted text
> > There are several places in op.c that recursively do a partial or full > treewalk of the subtree associated with a node. A quick scan of op.c for > likely recursive functions turns up: > > Perl_op_free > S_find_and_forget_pmops > Perl_scalar > Perl_scalarvoid > Perl_list > S_finalize_op > Perl_doref > S_my_kid > S_aassign_common_vars > > (Then of course there's Perl_rpeep, which doesn't recursively walk the > tree, but instead follows op_next nodes, recursively scanning whenever > there's a branch, such as a LOGOP with an op_other field). > > Now, it's quite simple (especially with machine-generated code) to create > an optree that's arbitrarily deep. For example: > > my $line = "\$cond ? \$a : \n"; > my $code = ($line x 10000) . "\$b;\n"; > eval $code; > > This creates a 10,000 depth tree. > > Any function which walks the tree recursively (or which uses a small fixed > stack to avoid some recursion) is going to crash on a suitably > pathological piece of code. > > Which leads me to speculate... > > The problem really is that there is no pointer back from the kids to the > parent op. Thus to walk the tree you need a stack (C or otherwise) to > record your current op_sibling iterator for every depth in the tree. > > If hypothetically the last kid in an op_sibling chain had a pointer back > to its parent, e.g. > > parent > | > kid1 --> kid2 ---> kid3 ---> NULL > | > kid4 ---> kid5 --> kid6 ---> NULL > > becomes > > parent <----------------- > | \ > kid1 --> kid2 ---> kid3 -/ > | ^ > | \ > | -------------------- > | \ > kid4 ---> kid5 --> kid6 -/ > > Then walking the whole subtree can be done simply by iteratively > following (op_first || op_sibling) until we arrive back at the original > node. > > For this to work, we need a temporary 'already processed' flag on ops to > show that they've already been visited (so in the above when we arrive
back Show quoted text
> at kid2 we know to follow op_sibling rather than op_first). Perhaps op_opt > will suffice?. > > Also, we need to temporarily set the op_sibling of the last kid from NULL > to instead point back at its parent; we revert this to NULL once we visit > the kid in question (which may involve needing another flag bit). > > Actually, if we know we're at the last op_sibling and so the next op will > be the parent, then we don't need an 'already processed' flag: we know > that the next node has already been done. Or maybe the tmp pointer should > point to parent->op_sibling rather than to parent, also avoiding the need > for an 'already processed' flag. > > Of course this is all predicated on the actions being performed for > each tree node not choking on the fake extra pointer on the last kid. > I don't know whether this would be an issue. > > I had a brief attempt to see if I could get a proof-of-concept > implementation to work with op_free, but that turns out to be a bit > complicated by the fact that some actions are performed before the kids > are walked, and some after (and of course the op itself gets freed). > So I gave up as I haven't got time to look into this deeply at the moment. > > So I thought I'd throw it into the ring instead. >
Instead of Thykier's 10 deep fixed len mini stack, or davem's adding return to root OP * to end of a branch on optree, here is my WAG idea. Do an ENTER, use SAVEDESTRUCTOR_X for every OP * encountered, then do a LEAVE, and the ops will free in a linear flattened model using an malloced unlimited length (OS user mode memory limit) stack (save stack)? I'll guess from the other posts in this ticket so far, that these op tree deep recursion bugs are something/some function needs to trace around the outside of the tree, linearlizing the tree. A combination of for loops and recursion are used to do this in the current implementation. Is this a correct explanation? Also, in the for loop+recusion call stacks, is the algorithm, where x is the number of OP structs in the sub, x*x, or x! or just plain x? I'm trying to figure out if there is a performance problem/big O of these op tree recursion crashes. -- bulk88 ~ bulk88 at hotmail.com
CC: perl5-porters [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Thu, 18 Jul 2013 20:22:00 +0100
To: Dave Mitchell <davem [...] iabyn.com>
From: hv [...] crypt.org
Download (untitled) / with headers
text/plain 3.8k
Dave Mitchell <davem@iabyn.com> wrote: :There are several places in op.c that recursively do a partial or full :treewalk of the subtree associated with a node. A quick scan of op.c for :likely recursive functions turns up: : : Perl_op_free : S_find_and_forget_pmops : Perl_scalar : Perl_scalarvoid : Perl_list : S_finalize_op : Perl_doref : S_my_kid : S_aassign_common_vars : :(Then of course there's Perl_rpeep, which doesn't recursively walk the :tree, but instead follows op_next nodes, recursively scanning whenever :there's a branch, such as a LOGOP with an op_other field). : :Now, it's quite simple (especially with machine-generated code) to create :an optree that's arbitrarily deep. For example: : : my $line = "\$cond ? \$a : \n"; : my $code = ($line x 10000) . "\$b;\n"; : eval $code; : :This creates a 10,000 depth tree. : :Any function which walks the tree recursively (or which uses a small fixed :stack to avoid some recursion) is going to crash on a suitably :pathological piece of code. : :Which leads me to speculate... : :The problem really is that there is no pointer back from the kids to the :parent op. Thus to walk the tree you need a stack (C or otherwise) to :record your current op_sibling iterator for every depth in the tree. : :If hypothetically the last kid in an op_sibling chain had a pointer back :to its parent, e.g. : : parent : | : kid1 --> kid2 ---> kid3 ---> NULL : | : kid4 ---> kid5 --> kid6 ---> NULL : :becomes : : parent <----------------- : | \ : kid1 --> kid2 ---> kid3 -/ : | ^ : | \ : | -------------------- : | \ : kid4 ---> kid5 --> kid6 -/ : :Then walking the whole subtree can be done simply by iteratively :following (op_first || op_sibling) until we arrive back at the original :node. : :For this to work, we need a temporary 'already processed' flag on ops to :show that they've already been visited (so in the above when we arrive back :at kid2 we know to follow op_sibling rather than op_first). Perhaps op_opt :will suffice?. : :Also, we need to temporarily set the op_sibling of the last kid from NULL :to instead point back at its parent; we revert this to NULL once we visit :the kid in question (which may involve needing another flag bit). : :Actually, if we know we're at the last op_sibling and so the next op will :be the parent, then we don't need an 'already processed' flag: we know :that the next node has already been done. Or maybe the tmp pointer should :point to parent->op_sibling rather than to parent, also avoiding the need :for an 'already processed' flag. : :Of course this is all predicated on the actions being performed for :each tree node not choking on the fake extra pointer on the last kid. :I don't know whether this would be an issue. : :I had a brief attempt to see if I could get a proof-of-concept :implementation to work with op_free, but that turns out to be a bit :complicated by the fact that some actions are performed before the kids :are walked, and some after (and of course the op itself gets freed). :So I gave up as I haven't got time to look into this deeply at the moment. : :So I thought I'd throw it into the ring instead. Maybe I misrepresent it, but it sounds rather an expensive way - in memory and complexity - to cope with the pathological cases. I feel like there ought to be something rather lighter-weight that performs well in normal cases. If it performs well in pathological cases as well, all the better, but (other than trying not to crash) I don't feel they're what we should optimize for. Moving the C-stack recursion to an optree-traversal stack that grows at need (but rarely needs to in any but pathological cases) sounds as if it should suffice, and as if it could involve rather less complexity. Hugo
CC: perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Fri, 19 Jul 2013 00:15:04 +0200
From: Niels Thykier <niels [...] thykier.net>
Download (untitled) / with headers
text/plain 5.8k
On 2013-07-18 16:49, Dave Mitchell wrote: Show quoted text
> On Wed, Jul 17, 2013 at 11:28:48PM +0200, Niels Thykier wrote:
>> I have attached a prototype patch that solves the problem (at least for >> me). With the patch applied, I can run it with up to at least 2M >> without it crashing - I have not tested beyond that because perl starts >> to use >= 4GB of RAM around the 2M mark.
> > Some general thoughts and comments about this issue. > > There are several places in op.c that recursively do a partial or full > treewalk of the subtree associated with a node. A quick scan of op.c for > likely recursive functions turns up: > > [...] > > (Then of course there's Perl_rpeep, which doesn't recursively walk the > tree, but instead follows op_next nodes, recursively scanning whenever > there's a branch, such as a LOGOP with an op_other field). >
I agree that it seems like we are re-doing (partial) recursive walking quite a few times. So it would probably be worth it to have some utilities to make it easier. Show quoted text
> Now, it's quite simple (especially with machine-generated code) to create > an optree that's arbitrarily deep. For example: > > my $line = "\$cond ? \$a : \n"; > my $code = ($line x 10000) . "\$b;\n"; > eval $code; > > This creates a 10,000 depth tree. >
Seems to be a nice memory friendly stack-trashing test case. :) Although it seems to take quite a while to compile for larger numbers. Show quoted text
> Any function which walks the tree recursively (or which uses a small fixed > stack to avoid some recursion) is going to crash on a suitably > pathological piece of code. > > Which leads me to speculate... > > The problem really is that there is no pointer back from the kids to the > parent op. Thus to walk the tree you need a stack (C or otherwise) to > record your current op_sibling iterator for every depth in the tree. > > If hypothetically the last kid in an op_sibling chain had a pointer back > to its parent, e.g. > > parent > | > kid1 --> kid2 ---> kid3 ---> NULL > | > kid4 ---> kid5 --> kid6 ---> NULL > > becomes > > parent <----------------- > | \ > kid1 --> kid2 ---> kid3 -/ > | ^ > | \ > | -------------------- > | \ > kid4 ---> kid5 --> kid6 -/ > > Then walking the whole subtree can be done simply by iteratively > following (op_first || op_sibling) until we arrive back at the original > node. >
Interesting proposal - if nothing else, we could avoid having to deal with dynamic memory allocation for traversing the tree (once it has been fully constructed that is). Show quoted text
> For this to work, we need a temporary 'already processed' flag on ops to > show that they've already been visited (so in the above when we arrive back > at kid2 we know to follow op_sibling rather than op_first). Perhaps op_opt > will suffice?. >
Mmm, we might have to restore its original value again. Admittedly I don't remember the peep optimiser fully, but if it uses any of the functions above, we don't want calling them to leave some nodes unoptimised. Also, it would possibly make it difficult for the peep optimiser to use this approach (for similar reasons). Show quoted text
> Also, we need to temporarily set the op_sibling of the last kid from NULL > to instead point back at its parent; we revert this to NULL once we visit > the kid in question (which may involve needing another flag bit). >
If you revert it back to NULL, how are you going to use it for traversing the tree. If I understand this part correctly, you would end up adding the parent-link back, then use it and remove it again several times. And I am pretty sure the part of adding the parent-link is not going to be easy without recursion or some helper stack/queue. Show quoted text
> Actually, if we know we're at the last op_sibling and so the next op will > be the parent, then we don't need an 'already processed' flag: we know > that the next node has already been done. Or maybe the tmp pointer should > point to parent->op_sibling rather than to parent, also avoiding the need > for an 'already processed' flag. >
Are you sure this will work for all cases, e.g. the peep optimiser makes the following comment about loop ops: /* a while(1) loop doesn't have an op_next that escapes the * loop, so we have to explicitly follow the op_lastop to * process the rest of the code */ (This is an honest question - I am by no means an expert on ops of any kind) Show quoted text
> Of course this is all predicated on the actions being performed for > each tree node not choking on the fake extra pointer on the last kid. > I don't know whether this would be an issue. >
I suspect something will croak/while(1)-loop on it, but I definitely find this an interesting alternative (particularly due to its possible O(1) memory usage). Show quoted text
> I had a brief attempt to see if I could get a proof-of-concept > implementation to work with op_free, but that turns out to be a bit > complicated by the fact that some actions are performed before the kids > are walked, and some after (and of course the op itself gets freed). > So I gave up as I haven't got time to look into this deeply at the moment. > > So I thought I'd throw it into the ring instead. >
I tried a different approach that for op_free in the attached patch - it /doesn't/ work, but I had to refactor part of op_free as a side-effect. Part of this refactoring might help you do your proof-of-concept though. The basic idea behind my patch was to abuse the op_next as a backlink doing free (under the assumption that "about to be freed" => "free general purpose memory"). In theory, it is also stackless like your idea, but it works only for free (as the traversion is destructive). Sadly, this seems to break perl causing many scripts to do "nothing at all". Possibly a bug in my implementation or in my assumption. Anyway, hope it helps you. ~Niels

Message body is not shown because sender requested not to inline it.

CC: perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Fri, 19 Jul 2013 00:18:17 +0200
From: Niels Thykier <niels [...] thykier.net>
Download (untitled) / with headers
text/plain 1.5k
On 2013-07-18 13:27, Nicholas Clark wrote: Show quoted text
> On Thu, Jul 18, 2013 at 01:19:05PM +0200, Niels Thykier wrote:
>> [...]
> > Yes, typically we have been re-indenting when adding scopes. So you're right > that the answer isn't as obvious as it first seemed. > > In this case, I think for ease of review the best course of action would > have been to attach the "proper" diff and put a whitespace-ignoring diff > inline in your message. > > (Because I'm unaware of any means for a reviewer to generate that diff without > having to > 1) checkout the correct parent version > 2) apply your patch > 3) run diff themselves > > whereas you are in a position to do just step 3, and save anyone else having > to quit their e-mail client to duplicate work) >
True, I should have thought of that. Show quoted text
>> In regards to the spaces used. As I understood it, the "desired" >> intention is " ", "\t", "\t ", "\t\t". So that is what I have >> been using so far. If it is wrong, then by all means do correct me so I >> don't include it in future patches.
> > There's an editor block at the bottom of each file which is supposed to get > (at least) emacs and vi to indent at 4 columns, and expand tabs to spaces. > Historically most of the code has hard tabs, and the alignment mostly seems > to assume a tabstop is at 8 spaces, but the rough plan is to eliminate tabs > on any line that gets changed for any other reason. The intent is to avoid > the "blame" history of files (at least of the complex old C code) being > confused by having whitespace only changes. > > Nicholas Clark >
Noted. ~Niels
RT-Send-CC: perl5-porters [...] perl.org, niels [...] thykier.net
Download (untitled) / with headers
text/plain 1.2k
On Thu Jul 18 15:15:54 2013, niels@thykier.net wrote: Show quoted text
> On 2013-07-18 16:49, Dave Mitchell wrote:
> > For this to work, we need a temporary 'already processed' flag on
> ops to
> > show that they've already been visited (so in the above when we
> arrive back
> > at kid2 we know to follow op_sibling rather than op_first). Perhaps
> op_opt
> > will suffice?. > >
> > Mmm, we might have to restore its original value again. Admittedly I > don't remember the peep optimiser fully, but if it uses any of the > functions above, we don't want calling them to leave some nodes > unoptimised. > Also, it would possibly make it difficult for the peep optimiser to > use this approach (for similar reasons).
I don’t think we need any extra flag here. for each op { if o->op_sibling is a list op and o->op_sibling->op_last == o, then next_op_to_look_at = o->op_sibling->op_sibling o->op_sibling = NULL; do our stuff ... } I think the correct check for ‘is this sibling actually the parent?’ would be: if (o->op_sibling->op_flags & OPf_KIDS && ( o->op_sibling->op_first == o /* UNOP */ || (o->op_sibling->op_first->op_sibling /* LISTOP */ && o->op_sibling->op_last == o) )) -- Father Chrysostomos
CC: perl5-porters [...] perl.org, perlbug-followup [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Fri, 19 Jul 2013 00:56:22 +0100
To: Niels Thykier <niels [...] thykier.net>
From: Dave Mitchell <davem [...] iabyn.com>
Download (untitled) / with headers
text/plain 4.2k
On Fri, Jul 19, 2013 at 12:15:04AM +0200, Niels Thykier wrote: Show quoted text
> > For this to work, we need a temporary 'already processed' flag on ops to > > show that they've already been visited (so in the above when we arrive back > > at kid2 we know to follow op_sibling rather than op_first). Perhaps op_opt > > will suffice?. > >
> > Mmm, we might have to restore its original value again. Admittedly I > don't remember the peep optimiser fully, but if it uses any of the > functions above, we don't want calling them to leave some nodes unoptimised. > Also, it would possibly make it difficult for the peep optimiser to > use this approach (for similar reasons).
Note that my suggestion is specifically for the treewalker functions (process an op then its kids); the peephole optimiser isn't a treewalker (it follows op_next's, not kids). Show quoted text
>
> > Also, we need to temporarily set the op_sibling of the last kid from NULL > > to instead point back at its parent; we revert this to NULL once we visit > > the kid in question (which may involve needing another flag bit). > >
> > If you revert it back to NULL, how are you going to use it for > traversing the tree. If I understand this part correctly, you would end > up adding the parent-link back, then use it and remove it again several > times. And I am pretty sure the part of adding the parent-link is not > going to be easy without recursion or some helper stack/queue.
Perhaps a specific example: A lot of the recursive tree-walker functions look like, in essence: Perl_foo(OP *o) { switch (o->op_type) { ... fix up o in some way } /* visit o's kids */ if (o->op_flags & OPf_KIDS) { OP *kid = cUNOPo->op_first; while (kid) { foo(kid); kid = kid->op_sibling; } } } I would change it to look like (somewhat handwavy): Perl_foo(OP *o) { while (o) { if (o->op_fake_sibling_flag) { o->op_fake_sibling_flag = 0; o->op_sibling = NULL; } switch (o->op_type) { ... fix up o in some way } /* visit o's kids */ if (o->op_flags & OPf_KIDS) { OP *lastkid = (loop through op_sibling chain to find last kid); lastkid->op_sibling = o; /* tmp loop back to parents */ lastkid->op_fake_sibling_flag = 1; o = lastkid; } else o = o->op_sibling; } } The above code is not workable - for example I don't address how to halt once we've parsed the whole subtree and ended back up at the original o; but what it does demonstrate is the *temporary* nature of the fixup; when we're about to process the list of kids, we hack the last kid; when we reach the last kid, we unhack it. Show quoted text
>
> > Actually, if we know we're at the last op_sibling and so the next op will > > be the parent, then we don't need an 'already processed' flag: we know > > that the next node has already been done. Or maybe the tmp pointer should > > point to parent->op_sibling rather than to parent, also avoiding the need > > for an 'already processed' flag. > >
> > Are you sure this will work for all cases, e.g. the peep optimiser makes > the following comment about loop ops: > > /* a while(1) loop doesn't have an op_next that escapes the > * loop, so we have to explicitly follow the op_lastop to > * process the rest of the code */ > > (This is an honest question - I am by no means an expert on ops of any kind)
Again, this suggestion doesn't apply to the peephole optimiser. Show quoted text
> I tried a different approach that for op_free in the attached patch - it > /doesn't/ work, but I had to refactor part of op_free as a side-effect. > Part of this refactoring might help you do your proof-of-concept though. > > The basic idea behind my patch was to abuse the op_next as a backlink > doing free (under the assumption that "about to be freed" => "free > general purpose memory"). In theory, it is also stackless like your > idea, but it works only for free (as the traversion is destructive). > Sadly, this seems to break perl causing many scripts to do "nothing at > all". Possibly a bug in my implementation or in my assumption. Anyway, > hope it helps you.
As I mentioned earlier, I haven't really got time to look at the deeply at the moment. -- "You're so sadly neglected, and often ignored. A poor second to Belgium, When going abroad." -- Monty Python, "Finland"
CC: perl5-porters [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Fri, 19 Jul 2013 01:11:51 +0100
To: bulk88 via RT <perlbug-followup [...] perl.org>
From: Dave Mitchell <davem [...] iabyn.com>
Download (untitled) / with headers
text/plain 2.4k
On Thu, Jul 18, 2013 at 10:05:09AM -0700, bulk88 via RT wrote: Show quoted text
> Instead of Thykier's 10 deep fixed len mini stack, or davem's adding > return to root OP * to end of a branch on optree, here is my WAG idea. > > Do an ENTER, use SAVEDESTRUCTOR_X for every OP * encountered, then do a > LEAVE, and the ops will free in a linear flattened model using an > malloced unlimited length (OS user mode memory limit) stack (save stack)?
Unfortunately I don't think that would work, since the save stack is per interpreter, while the op tree is shared among threads (so if the thread that compiled the code exits, the op tree is freed, screwing any threads still live and using that code). Show quoted text
> I'll guess from the other posts in this ticket so far, that these op > tree deep recursion bugs are something/some function needs to trace > around the outside of the tree, linearlizing the tree. A combination of > for loops and recursion are used to do this in the current > implementation. Is this a correct explanation?
Not really. During compilation it's sometimes required to visit every node in a tree (or part of a tree) in either depth-first or breath-first order. For example when compiling an assignment op (where expr is a subtree that's already been compiled): @foo = expr Its only at this point that the compiler knows that expr will be evaluated in list context. It calls Perl_list() on the top node of the subtree representing expr. This will mark that node as list context, then (if appropriate) recursively visit any children of that node; skipping any node whose context has already been determined. As the code is compiled, more and more small subtree are joined into bigger trees, until you end up with a single tree containing the whole function, with Perl_scalar() and Perl_list() and others being called multiple times on various subtrees (but usually a particular subtree is only walked once). As a final compilation act, the whole sub's optree is walked once in finalize_optree() to do any final fixups. Then when a sub is freed, its optree is recursively freed using a similar treewalk. Show quoted text
> Also, in the for loop+recusion call stacks, is the algorithm, where x is > the number of OP structs in the sub, x*x, or x! or just plain x? I'm > trying to figure out if there is a performance problem/big O of these op > tree recursion crashes.
They should be plain x. -- I've often wanted to drown my troubles, but I can't get my wife to go swimming.
CC: perl5-porters [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Fri, 19 Jul 2013 01:19:39 +0100
To: hv [...] crypt.org
From: Dave Mitchell <davem [...] iabyn.com>
Download (untitled) / with headers
text/plain 1.3k
On Thu, Jul 18, 2013 at 08:22:00PM +0100, hv@crypt.org wrote: Show quoted text
> Maybe I misrepresent it, but it sounds rather an expensive way - in memory > and complexity - to cope with the pathological cases. I feel like there > ought to be something rather lighter-weight that performs well in normal > cases. If it performs well in pathological cases as well, all the better, > but (other than trying not to crash) I don't feel they're what we should > optimize for. > > Moving the C-stack recursion to an optree-traversal stack that grows at > need (but rarely needs to in any but pathological cases) sounds as if it > should suffice, and as if it could involve rather less complexity.
I think both approaches would have a similar level of complexity. They'll both make what was a simple recursive function more messy.. The advantage of my approach would be that no new data needs mallocing(); the entries in the traversal stack are essentially being temporarily being stored in the otherwise NULL op_sibling fields of the last kid at each depth. I don't think the code for my approach need be messy, but it would require some hard thinking to do right - i.e. to get exactly the right algorithm so that everything just comes out in the wash and doesn't require lots of flags and messing about. But I'm not opposed to the mallocing-a-traversal stack either. -- Atheism is a religion like not collecting stamps is a hobby
CC: perl5-porters [...] perl.org, niels [...] thykier.net
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Date: Fri, 19 Jul 2013 01:26:18 +0100
To: Father Chrysostomos via RT <perlbug-followup [...] perl.org>
From: Dave Mitchell <davem [...] iabyn.com>
Download (untitled) / with headers
text/plain 977b
On Thu, Jul 18, 2013 at 03:46:31PM -0700, Father Chrysostomos via RT wrote: Show quoted text
> I think the correct check for ‘is this sibling actually the parent?’ > would be: > > if (o->op_sibling->op_flags & OPf_KIDS && ( > o->op_sibling->op_first == o /* UNOP */ > || (o->op_sibling->op_first->op_sibling /* LISTOP */ && > o->op_sibling->op_last == o) > ))
On my quick play with this last night I found that it wasn't simple, for a given node o, to determine its last child. For example LOGOPs don't have a pointer to the second child. I tried in op_free() to determine the last kid by doing a switch on the OP class (e.g. OA_LISTOP) and handling each class, then comparing that with a brute-force kid=cUNOPo->op_first; while (kid && kid->op_sibling) kid->op_sibling and asserting that the two results were always the same. I found so many exceptions that I quickly gave up. -- Dave's first rule of Opera: If something needs saying, say it: don't warble it.
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 117b
Can someone add a HasPatch RT tag to this ticket now that there is a patch in it? -- bulk88 ~ bulk88 at hotmail.com
RT-Send-CC: perl5-porters [...] perl.org, niels [...] thykier.net
Download (untitled) / with headers
text/plain 1.8k
On Wed Jul 17 14:29:33 2013, niels@thykier.net wrote: Show quoted text
> Hi, > > I cannot reproduce the issue in S_finalize_op on blead[1]. It is > possible that it has been "fixed" somehow (or we got different > architectures). > > On the other hand, I can reproduce the crash caused by: > > perl -e'eval "sub{".q"$a+"x shift . "}"' 500000 > > > I have attached a prototype patch that solves the problem (at least for > me). With the patch applied, I can run it with up to at least 2M > without it crashing - I have not tested beyond that because perl starts > to use >= 4GB of RAM around the 2M mark. > A more memory friendly test case is definitely welcome. :) > > For the reviewer(s): the patch is much easier to read by ignoring space > changes[2]. It re-uses the basic principe of the DEFER marco used in > the peephole optimizer. The "major" difference is that it uses a > fixed-size stack rather than a fixed-size queue. The size of the queue > did not seem to matter a lot (even with MAX_DEFERRED reduced to 2 was > the crash avoided in original test case). > > The test suite showed no regression, perl was configured with: > ./Configure -des -Dusedevel > > ~Niels > > > [1] I have been using code suggested by Dave Mitchell (rewritten as a > perl one-liner) > > ./perl -e 'my $code = q[my $i = 0; if ($i) { print } ] . "\n";' > -e '$code .= q[ elsif ($i) { print } ] . "\n" for 1..$ARGV[0];' > -e 'eval $code' 10000 > > [2] Compare > > $ git diff --ignore-all-space --stat > op.c | 37 [...] > 1 file changed, 34 insertions(+), 3 deletions(-) > > versus. > > $ git diff --stat > op.c | 141 [...] > 1 file changed, 86 insertions(+), 55 deletions(-) >
Would you be willing to finish this patch, either making it malloc a deferred stack when necessary (presumably a rare case) or using Dave Mitchell’s op_sibling technique? -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
On Wed Jul 24 12:37:14 2013, sprout wrote: Show quoted text
> Would you be willing to finish this patch, either making it malloc a > deferred stack when necessary (presumably a rare case) or using Dave > Mitchell’s op_sibling technique?
I've attached a variant of Niels' patch, included inline below as a whitespace ignoring diff. Without the patch C< ./perl -e eval\ "sub{".q"$a+"x\ shift\ .\ "}" 500000 > crashed deep in op_free(), with the patch it didn't. I was a bit worried about increasing the allocation linearly would result in a performance issue, but that turned out to be faster than a simple exponential allocation (on Linux, YMMV.) Tony diff --git a/op.c b/op.c index 59a3541..1460995 100644 --- a/op.c +++ b/op.c @@ -675,11 +675,29 @@ optree. =cut */ +#define DEFERRED_STEP 100 +#define DEFER(o) \ + STMT_START { \ + if (UNLIKELY(defer_ix == (defer_stack_alloc-1))) { \ + defer_stack_alloc += DEFERRED_STEP; \ + assert(defer_stack_alloc > 0); \ + Renew(defer_stack, defer_stack_alloc, OP *); \ + } \ + defer_stack[++defer_ix] = o; \ + } STMT_END + +#define POP_DEFERRED() (defer_ix >= 0 ? defer_stack[defer_ix--] : (OP *)NULL) + void Perl_op_free(pTHX_ OP *o) { dVAR; OPCODE type; + SSize_t defer_ix = -1; + SSize_t defer_stack_alloc = 0; + OP **defer_stack = NULL; + + do { /* Though ops may be freed twice, freeing the op after its slab is a big no-no. */ @@ -687,7 +705,7 @@ Perl_op_free(pTHX_ OP *o) /* During the forced freeing of ops after compilation failure, kidops may be freed before their parents. */ if (!o || o->op_type == OP_FREED) - return; + continue; type = o->op_type; @@ -714,7 +732,7 @@ Perl_op_free(pTHX_ OP *o) /* Need to find and remove any pattern match ops from the list we maintain for reset(). */ find_and_forget_pmops(o); - return; + continue; } } break; @@ -732,7 +750,16 @@ Perl_op_free(pTHX_ OP *o) OP *kid, *nextkid; for (kid = cUNOPo->op_first; kid; kid = nextkid) { nextkid = OP_SIBLING(kid); /* Get before next freeing kid */ + if (!kid || kid->op_type == OP_FREED) + /* During the forced freeing of ops after + compilation failure, kidops may be freed before + their parents. */ + continue; + if (!(kid->op_flags & OPf_KIDS)) + /* If it has no kids, just free it now */ op_free(kid); + else + DEFER(kid); } } if (type == OP_NULL) @@ -753,8 +780,15 @@ Perl_op_free(pTHX_ OP *o) if (PL_op == o) PL_op = NULL; #endif + } while ( (o = POP_DEFERRED()) ); + + Safefree(defer_stack); } +#undef DEFER +#undef POP_DEFERRED +#undef DEFERRED_STEP + void Perl_op_clear(pTHX_ OP *o) {
Subject: 0001-perl-108276-avoid-deep-recursion-in-Perl_op_free.patch
From 5444ca11479885c3114d8b6ba037bcaeaa187c79 Mon Sep 17 00:00:00 2001 From: Tony Cook <tony@develop-help.com> Date: Tue, 28 Oct 2014 11:18:28 +1100 Subject: [perl #108276] avoid deep recursion in Perl_op_free() Based on a patch by Niels Thykier, with the following changes: - the stack is allocated dynamically, rather than with a fixed depth of 10 - reordered the loop to avoid pushing the argument and immediately popping it. This wasn't a big deal with the auto stack, but avoids a Newx() call for freeing leaf nodes --- op.c | 158 ++++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 96 insertions(+), 62 deletions(-) diff --git a/op.c b/op.c index 59a3541..1460995 100644 --- a/op.c +++ b/op.c @@ -675,86 +675,120 @@ optree. =cut */ +#define DEFERRED_STEP 100 +#define DEFER(o) \ + STMT_START { \ + if (UNLIKELY(defer_ix == (defer_stack_alloc-1))) { \ + defer_stack_alloc += DEFERRED_STEP; \ + assert(defer_stack_alloc > 0); \ + Renew(defer_stack, defer_stack_alloc, OP *); \ + } \ + defer_stack[++defer_ix] = o; \ + } STMT_END + +#define POP_DEFERRED() (defer_ix >= 0 ? defer_stack[defer_ix--] : (OP *)NULL) + void Perl_op_free(pTHX_ OP *o) { dVAR; OPCODE type; + SSize_t defer_ix = -1; + SSize_t defer_stack_alloc = 0; + OP **defer_stack = NULL; - /* Though ops may be freed twice, freeing the op after its slab is a - big no-no. */ - assert(!o || !o->op_slabbed || OpSLAB(o)->opslab_refcnt != ~(size_t)0); - /* During the forced freeing of ops after compilation failure, kidops - may be freed before their parents. */ - if (!o || o->op_type == OP_FREED) - return; + do { - type = o->op_type; + /* Though ops may be freed twice, freeing the op after its slab is a + big no-no. */ + assert(!o || !o->op_slabbed || OpSLAB(o)->opslab_refcnt != ~(size_t)0); + /* During the forced freeing of ops after compilation failure, kidops + may be freed before their parents. */ + if (!o || o->op_type == OP_FREED) + continue; - /* an op should only ever acquire op_private flags that we know about. - * If this fails, you may need to fix something in regen/op_private */ - if (o->op_ppaddr == PL_ppaddr[o->op_type]) { - assert(!(o->op_private & ~PL_op_private_valid[type])); - } + type = o->op_type; - if (o->op_private & OPpREFCOUNTED) { - switch (type) { - case OP_LEAVESUB: - case OP_LEAVESUBLV: - case OP_LEAVEEVAL: - case OP_LEAVE: - case OP_SCOPE: - case OP_LEAVEWRITE: - { - PADOFFSET refcnt; - OP_REFCNT_LOCK; - refcnt = OpREFCNT_dec(o); - OP_REFCNT_UNLOCK; - if (refcnt) { - /* Need to find and remove any pattern match ops from the list - we maintain for reset(). */ - find_and_forget_pmops(o); - return; - } - } - break; - default: - break; - } - } + /* an op should only ever acquire op_private flags that we know about. + * If this fails, you may need to fix something in regen/op_private */ + if (o->op_ppaddr == PL_ppaddr[o->op_type]) { + assert(!(o->op_private & ~PL_op_private_valid[type])); + } - /* Call the op_free hook if it has been set. Do it now so that it's called - * at the right time for refcounted ops, but still before all of the kids - * are freed. */ - CALL_OPFREEHOOK(o); + if (o->op_private & OPpREFCOUNTED) { + switch (type) { + case OP_LEAVESUB: + case OP_LEAVESUBLV: + case OP_LEAVEEVAL: + case OP_LEAVE: + case OP_SCOPE: + case OP_LEAVEWRITE: + { + PADOFFSET refcnt; + OP_REFCNT_LOCK; + refcnt = OpREFCNT_dec(o); + OP_REFCNT_UNLOCK; + if (refcnt) { + /* Need to find and remove any pattern match ops from the list + we maintain for reset(). */ + find_and_forget_pmops(o); + continue; + } + } + break; + default: + break; + } + } - if (o->op_flags & OPf_KIDS) { - OP *kid, *nextkid; - for (kid = cUNOPo->op_first; kid; kid = nextkid) { - nextkid = OP_SIBLING(kid); /* Get before next freeing kid */ - op_free(kid); - } - } - if (type == OP_NULL) - type = (OPCODE)o->op_targ; + /* Call the op_free hook if it has been set. Do it now so that it's called + * at the right time for refcounted ops, but still before all of the kids + * are freed. */ + CALL_OPFREEHOOK(o); + + if (o->op_flags & OPf_KIDS) { + OP *kid, *nextkid; + for (kid = cUNOPo->op_first; kid; kid = nextkid) { + nextkid = OP_SIBLING(kid); /* Get before next freeing kid */ + if (!kid || kid->op_type == OP_FREED) + /* During the forced freeing of ops after + compilation failure, kidops may be freed before + their parents. */ + continue; + if (!(kid->op_flags & OPf_KIDS)) + /* If it has no kids, just free it now */ + op_free(kid); + else + DEFER(kid); + } + } + if (type == OP_NULL) + type = (OPCODE)o->op_targ; - if (o->op_slabbed) - Slab_to_rw(OpSLAB(o)); + if (o->op_slabbed) + Slab_to_rw(OpSLAB(o)); - /* COP* is not cleared by op_clear() so that we may track line - * numbers etc even after null() */ - if (type == OP_NEXTSTATE || type == OP_DBSTATE) { - cop_free((COP*)o); - } + /* COP* is not cleared by op_clear() so that we may track line + * numbers etc even after null() */ + if (type == OP_NEXTSTATE || type == OP_DBSTATE) { + cop_free((COP*)o); + } - op_clear(o); - FreeOp(o); + op_clear(o); + FreeOp(o); #ifdef DEBUG_LEAKING_SCALARS - if (PL_op == o) - PL_op = NULL; + if (PL_op == o) + PL_op = NULL; #endif + } while ( (o = POP_DEFERRED()) ); + + Safefree(defer_stack); } +#undef DEFER +#undef POP_DEFERRED +#undef DEFERRED_STEP + void Perl_op_clear(pTHX_ OP *o) { -- 1.7.10.4
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 474b
On Mon Oct 27 17:23:20 2014, tonyc wrote: Show quoted text
> On Wed Jul 24 12:37:14 2013, sprout wrote:
> > Would you be willing to finish this patch, either making it malloc a > > deferred stack when necessary (presumably a rare case) or using Dave > > Mitchell’s op_sibling technique?
> > I've attached a variant of Niels' patch, included inline below as a > whitespace ignoring diff.
Thank you. The patch looks good to me. I see no reason not to apply it. -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 493b
On Sun Jan 15 10:35:13 2012, bulk88 wrote: Show quoted text
> Perl lexer (???) has a deep recursion bug in Perl_scalarvoid when > given a very large Perl subroutine to run.  Perl_scalarvoid calls > itself over and over, for what I blindly guess is every opcode in the > sub.  If there are too many opcodes, C stack overflows.
The attached patches, in addition to my adaption of Neils' patch fixes your test case for me. This doesn't attempt to fix possible recusion between scalarvoid() and scalar(). Tony
Subject: 0001-perl-108276-avoid-deep-scalarvoid-self-recursion.patch
From 5e237da0d1ac7de20fc7784db00b6e08d36946b7 Mon Sep 17 00:00:00 2001 From: Tony Cook <tony@develop-help.com> Date: Wed, 29 Oct 2014 09:51:53 +1100 Subject: [perl #108276] avoid deep scalarvoid() self-recursion This fixes the original test case from the ticket. It may be possible for code that alternates recursion between scalarvoid() and scalar() to cause deep recursion, but I haven't seen an example that does it. This doesn't indent the scalarvoid() loop, which will be done in another ticket. --- op.c | 74 +++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/op.c b/op.c index 1460995..97d9f4a 100644 --- a/op.c +++ b/op.c @@ -109,6 +109,23 @@ recursive, but it's recursive on basic blocks, not on tree nodes. #define CALL_RPEEP(o) PL_rpeepp(aTHX_ o) #define CALL_OPFREEHOOK(o) if (PL_opfreehook) PL_opfreehook(aTHX_ o) +/* Used to avoid recursion through the op tree in scalarvoid() and + op_free() +*/ + +#define DEFERRED_OP_STEP 100 +#define DEFER_OP(o) \ + STMT_START { \ + if (UNLIKELY(defer_ix == (defer_stack_alloc-1))) { \ + defer_stack_alloc += DEFERRED_OP_STEP; \ + assert(defer_stack_alloc > 0); \ + Renew(defer_stack, defer_stack_alloc, OP *); \ + } \ + defer_stack[++defer_ix] = o; \ + } STMT_END + +#define POP_DEFERRED_OP() (defer_ix >= 0 ? defer_stack[defer_ix--] : (OP *)NULL) + /* remove any leading "empty" ops from the op_next chain whose first * node's address is stored in op_p. Store the updated address of the * first node in op_p. @@ -675,19 +692,6 @@ optree. =cut */ -#define DEFERRED_STEP 100 -#define DEFER(o) \ - STMT_START { \ - if (UNLIKELY(defer_ix == (defer_stack_alloc-1))) { \ - defer_stack_alloc += DEFERRED_STEP; \ - assert(defer_stack_alloc > 0); \ - Renew(defer_stack, defer_stack_alloc, OP *); \ - } \ - defer_stack[++defer_ix] = o; \ - } STMT_END - -#define POP_DEFERRED() (defer_ix >= 0 ? defer_stack[defer_ix--] : (OP *)NULL) - void Perl_op_free(pTHX_ OP *o) { @@ -759,7 +763,7 @@ Perl_op_free(pTHX_ OP *o) /* If it has no kids, just free it now */ op_free(kid); else - DEFER(kid); + DEFER_OP(kid); } } if (type == OP_NULL) @@ -780,15 +784,11 @@ Perl_op_free(pTHX_ OP *o) if (PL_op == o) PL_op = NULL; #endif - } while ( (o = POP_DEFERRED()) ); + } while ( (o = POP_DEFERRED_OP()) ); Safefree(defer_stack); } -#undef DEFER -#undef POP_DEFERRED -#undef DEFERRED_STEP - void Perl_op_clear(pTHX_ OP *o) { @@ -1600,17 +1600,23 @@ Perl_scalar(pTHX_ OP *o) } OP * -Perl_scalarvoid(pTHX_ OP *o) +Perl_scalarvoid(pTHX_ OP *arg) { dVAR; OP *kid; - SV *useless_sv = NULL; - const char* useless = NULL; SV* sv; U8 want; + SSize_t defer_stack_alloc = 0; + SSize_t defer_ix = -1; + OP **defer_stack = NULL; + OP *o = arg; PERL_ARGS_ASSERT_SCALARVOID; + do { + SV *useless_sv = NULL; + const char* useless = NULL; + if (o->op_type == OP_NEXTSTATE || o->op_type == OP_DBSTATE || (o->op_type == OP_NULL && (o->op_targ == OP_NEXTSTATE @@ -1623,13 +1629,14 @@ Perl_scalarvoid(pTHX_ OP *o) || (PL_parser && PL_parser->error_count) || o->op_type == OP_RETURN || o->op_type == OP_REQUIRE || o->op_type == OP_LEAVEWHEN) { - return o; + continue; } if ((o->op_private & OPpTARGET_MY) && (PL_opargs[o->op_type] & OA_TARGLEX))/* OPp share the meaning */ { - return scalar(o); /* As if inside SASSIGN */ + scalar(o); /* As if inside SASSIGN */ + continue; } o->op_flags = (o->op_flags & ~OPf_WANT) | OPf_WANT_VOID; @@ -1893,7 +1900,10 @@ Perl_scalarvoid(pTHX_ OP *o) case OP_ENTERGIVEN: case OP_ENTERWHEN: for (kid = OP_SIBLING(cUNOPo->op_first); kid; kid = OP_SIBLING(kid)) - scalarvoid(kid); + if (!(kid->op_flags & OPf_KIDS)) + scalarvoid(kid); + else + DEFER_OP(kid); break; case OP_NULL: @@ -1916,7 +1926,10 @@ Perl_scalarvoid(pTHX_ OP *o) case OP_LEAVEWHEN: kids: for (kid = cLISTOPo->op_first; kid; kid = OP_SIBLING(kid)) - scalarvoid(kid); + if (!(kid->op_flags & OPf_KIDS)) + scalarvoid(kid); + else + DEFER_OP(kid); break; case OP_LIST: /* If the first kid after pushmark is something that the padrange @@ -1942,7 +1955,8 @@ Perl_scalarvoid(pTHX_ OP *o) scalarkids(o); break; case OP_SCALAR: - return scalar(o); + scalar(o); + break; } if (useless_sv) { @@ -1956,7 +1970,11 @@ Perl_scalarvoid(pTHX_ OP *o) "Useless use of %s in void context", useless); } - return o; + } while ( (o = POP_DEFERRED_OP()) ); + + Safefree(defer_stack); + + return arg; } static OP * -- 1.7.10.4
Subject: 0002-perl-108276-re-indent-the-loop-body.patch

Message body is not shown because it is too large.

RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 781b
On Mon Jan 16 03:51:55 2012, davem wrote: Show quoted text
> On Sun, Jan 15, 2012 at 10:35:14AM -0800, bulk 88 wrote: > > The code can be simplified to the following: > > my $n = $ARGV[0]; > die unless $n =~ /^\d+$/; > > my $code = 'my $i = 0; if ($i) { print }' . "\n"; > $code .= 'elsif ($i) { print }' . "\n" for 1..$n; > eval $code; > > segfaults for me on blead with n >= about 5000. > > In blead, it's recursing in S_finalize_op rather than scalarvoid; not sure > whether this is instead of or in addition to a scalarvoid problem. >
Here's a patch that fixes the S_finalize_op() recursion, whitespace changes minimal Additionally another patch to re-indent the new loop, and another to use the new macros I added to declare and clean-up the DEFER_OP() stack. Tony
Subject: 0001-perl-108276-avoid-recursion-in-S_finalize_op.patch
From e7121e75f07de01236b37370154aa0661cd89734 Mon Sep 17 00:00:00 2001 From: Tony Cook <tony@develop-help.com> Date: Mon, 17 Nov 2014 17:10:25 +1100 Subject: [perl #108276] avoid recursion in S_finalize_op() This uses the same DEFER_OP() macro set as op_free() and scalarvoid() but required a bit more work to ensure that warnings are still produced in source order. --- op.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/op.c b/op.c index 00c1255..c0de23c 100644 --- a/op.c +++ b/op.c @@ -109,10 +109,33 @@ recursive, but it's recursive on basic blocks, not on tree nodes. #define CALL_RPEEP(o) PL_rpeepp(aTHX_ o) #define CALL_OPFREEHOOK(o) if (PL_opfreehook) PL_opfreehook(aTHX_ o) -/* Used to avoid recursion through the op tree in scalarvoid() and - op_free() +/* Used to avoid recursion through the op tree in scalarvoid(), + op_free() and S_finalize_op(). + + Add: + + DEFER_OP_DECLARE; + + at the top of the scope these are used in and: + + DEFER_OP_END; + + at any exit points. + + Use DEFER_OP(op) to push an op and POP_DEFERRED_OP() to get the next op + to process. + + DEFERRED_OP_ALLOC(sz, fill) allocates sz items at the top of the + stack and sets fill to a pointer to just beyond the last item. + This is used by S_finalize_op() to ensure children are processed in + source order. */ +#define DEFER_OP_DECLARE \ + SSize_t defer_ix = -1; \ + SSize_t defer_stack_alloc = 0; \ + OP **defer_stack = NULL +#define DEFER_OP_END Safefree(defer_stack) #define DEFERRED_OP_STEP 100 #define DEFER_OP(o) \ STMT_START { \ @@ -126,6 +149,18 @@ recursive, but it's recursive on basic blocks, not on tree nodes. #define POP_DEFERRED_OP() (defer_ix >= 0 ? defer_stack[defer_ix--] : (OP *)NULL) +#define DEFERRED_OP_ALLOC(sz, top) \ + STMT_START { \ + if (UNLIKELY(defer_ix + (sz) >= defer_stack_alloc)) { \ + defer_stack_alloc += \ + (sz) < DEFERRED_OP_STEP ? DEFERRED_OP_STEP : (sz); \ + assert(defer_stack_alloc > 0); \ + Renew(defer_stack, defer_stack_alloc, OP *); \ + } \ + defer_ix += (sz); \ + (top) = defer_stack + defer_ix + 1; \ + } STMT_END + /* remove any leading "empty" ops from the op_next chain whose first * node's address is stored in op_p. Store the updated address of the * first node in op_p. @@ -2170,9 +2205,11 @@ S_op_relocate_sv(pTHX_ SV** svp, PADOFFSET* targp) STATIC void S_finalize_op(pTHX_ OP* o) { - PERL_ARGS_ASSERT_FINALIZE_OP; + DEFER_OP_DECLARE; + PERL_ARGS_ASSERT_FINALIZE_OP; + do { switch (o->op_type) { case OP_NEXTSTATE: case OP_DBSTATE: @@ -2397,10 +2434,24 @@ S_finalize_op(pTHX_ OP* o) # endif } #endif + { + /* Count then fill from the top to ensure any diagnostics + are produced in order from the start of the code. + */ + SSize_t kid_count = 0; + OP **fill; + for (kid = cUNOPo->op_first; kid; kid = OP_SIBLING(kid)) + ++kid_count; + + DEFERRED_OP_ALLOC(kid_count, fill); - for (kid = cUNOPo->op_first; kid; kid = OP_SIBLING(kid)) - finalize_op(kid); + for (kid = cUNOPo->op_first; kid; kid = OP_SIBLING(kid)) + *--fill = kid; + } } + } while ( (o = POP_DEFERRED_OP()) ); + + DEFER_OP_END; } /* -- 1.7.10.4
Subject: 0002-perl-108276-re-indent-the-new-S_finalize_op-loop.patch

Message body is not shown because it is too large.

Subject: 0003-perl-108276-use-the-new-declare-and-clean-up-macros-.patch
From cf5d0ab47de426134b6c2b1934b698aed98ad650 Mon Sep 17 00:00:00 2001 From: Tony Cook <tony@develop-help.com> Date: Mon, 17 Nov 2014 17:35:10 +1100 Subject: [perl #108276] use the new declare and clean-up macros for the old uses --- op.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/op.c b/op.c index 45e9c16..ea97abf 100644 --- a/op.c +++ b/op.c @@ -732,9 +732,7 @@ Perl_op_free(pTHX_ OP *o) { dVAR; OPCODE type; - SSize_t defer_ix = -1; - SSize_t defer_stack_alloc = 0; - OP **defer_stack = NULL; + DEFER_OP_DECLARE; do { @@ -821,7 +819,7 @@ Perl_op_free(pTHX_ OP *o) #endif } while ( (o = POP_DEFERRED_OP()) ); - Safefree(defer_stack); + DEFER_OP_END; } void @@ -1649,9 +1647,7 @@ Perl_scalarvoid(pTHX_ OP *arg) OP *kid; SV* sv; U8 want; - SSize_t defer_stack_alloc = 0; - SSize_t defer_ix = -1; - OP **defer_stack = NULL; + DEFER_OP_DECLARE; OP *o = arg; PERL_ARGS_ASSERT_SCALARVOID; @@ -2014,7 +2010,7 @@ Perl_scalarvoid(pTHX_ OP *arg) } } while ( (o = POP_DEFERRED_OP()) ); - Safefree(defer_stack); + DEFER_OP_END; return arg; } -- 1.7.10.4
To: Tony Cook via RT <perlbug-followup [...] perl.org>
From: Dave Mitchell <davem [...] iabyn.com>
Date: Mon, 17 Nov 2014 12:48:44 +0000
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.2k
On Sun, Nov 16, 2014 at 10:42:19PM -0800, Tony Cook via RT wrote: Show quoted text
> On Mon Jan 16 03:51:55 2012, davem wrote:
> > On Sun, Jan 15, 2012 at 10:35:14AM -0800, bulk 88 wrote: > > > > The code can be simplified to the following: > > > > my $n = $ARGV[0]; > > die unless $n =~ /^\d+$/; > > > > my $code = 'my $i = 0; if ($i) { print }' . "\n"; > > $code .= 'elsif ($i) { print }' . "\n" for 1..$n; > > eval $code; > > > > segfaults for me on blead with n >= about 5000. > > > > In blead, it's recursing in S_finalize_op rather than scalarvoid; not sure > > whether this is instead of or in addition to a scalarvoid problem. > >
> > Here's a patch that fixes the S_finalize_op() recursion, whitespace changes minimal
Note that once PERL_OP_PARENT becomes the default in blead, the recursion issue in most of the tree-walking functions in op.c will become trivially fixable (the last op_sibling in each chain points back to the parent, so a tree can be walked without needing to maintain state.) -- More than any other time in history, mankind faces a crossroads. One path leads to despair and utter hopelessness. The other, to total extinction. Let us pray we have the wisdom to choose correctly. -- Woody Allen
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.2k
On Mon Nov 17 04:49:05 2014, davem wrote: Show quoted text
> Note that once PERL_OP_PARENT becomes the default in blead, the > recursion > issue in most of the tree-walking functions in op.c will become > trivially > fixable (the last op_sibling in each chain points back to the parent, > so > a tree can be walked without needing to maintain state.)
I started an attempt to use that chain, but unfortunately blead as it is now fails an assertion with -DPERL_OP_PARENT: tony@mars:.../git/perl$ make ./miniperl -Ilib make_ext.pl cpan/Archive-Tar/pm_to_blib MAKE="make" LIBPERL_A=libperl.a miniperl: op.c:2386: S_finalize_op: Assertion `kid->op_sibling == o' failed. 6 from cpan/Archive-Tar's Makefile.PL at make_ext.pl line 513. Warning: No Makefile! make[1]: Entering directory `/home/tony/dev/perl/git/perl/cpan/Archive-Tar' make[1]: *** No rule to make target `all'. Stop. make[1]: Leaving directory `/home/tony/dev/perl/git/perl/cpan/Archive-Tar' make[1]: Entering directory `/home/tony/dev/perl/git/perl/cpan/Archive-Tar' make[1]: *** No rule to make target `all'. Stop. make[1]: Leaving directory `/home/tony/dev/perl/git/perl/cpan/Archive-Tar' Unsuccessful make(cpan/Archive-Tar): code=512 at make_ext.pl line 564. make: *** [cpan/Archive-Tar/pm_to_blib] Error 2 Tony
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 2.9k
On Mon Nov 17 16:05:50 2014, tonyc wrote: Show quoted text
> On Mon Nov 17 04:49:05 2014, davem wrote:
> > Note that once PERL_OP_PARENT becomes the default in blead, the > > recursion > > issue in most of the tree-walking functions in op.c will become > > trivially > > fixable (the last op_sibling in each chain points back to the parent, > > so > > a tree can be walked without needing to maintain state.)
> > I started an attempt to use that chain, but unfortunately blead as it > is now fails an assertion with -DPERL_OP_PARENT: > > tony@mars:.../git/perl$ make > ./miniperl -Ilib make_ext.pl cpan/Archive-Tar/pm_to_blib MAKE="make" > LIBPERL_A=libperl.a > miniperl: op.c:2386: S_finalize_op: Assertion `kid->op_sibling == o' > failed. > 6 from cpan/Archive-Tar's Makefile.PL at make_ext.pl line 513. > Warning: No Makefile! > make[1]: Entering directory > `/home/tony/dev/perl/git/perl/cpan/Archive-Tar' > make[1]: *** No rule to make target `all'. Stop. > make[1]: Leaving directory `/home/tony/dev/perl/git/perl/cpan/Archive- > Tar' > make[1]: Entering directory > `/home/tony/dev/perl/git/perl/cpan/Archive-Tar' > make[1]: *** No rule to make target `all'. Stop. > make[1]: Leaving directory `/home/tony/dev/perl/git/perl/cpan/Archive- > Tar' > Unsuccessful make(cpan/Archive-Tar): code=512 at make_ext.pl line 564. > make: *** [cpan/Archive-Tar/pm_to_blib] Error 2
Build failure* bisected to: bad - could not build test-prep b46e009d94293e069270690750f6c669c6d0ce22 is the first bad commit commit b46e009d94293e069270690750f6c669c6d0ce22 Author: syber <syber@crazypanda.ru> Date: Thu Sep 4 22:08:59 2014 +0400 Make OP_METHOD* to be of new class METHOP Introduce a new opcode class, METHOP, which will hold class/method related info needed at runtime to improve performance of class/object method calls, then change OP_METHOD and OP_METHOD_NAMED from being UNOP/SVOP to being METHOP. Note that because OP_METHOD is a UNOP with an op_first, while OP_METHOD_NAMED is an SVOP, the first field of the METHOP structure is a union holding either op_first or op_sv. This was seen as less messy than having to introduce two new op classes. The new op class's character is '.' Nothing has changed in functionality and/or performance by this commit. It just introduces new structure which will be extended with extra fields and used in later commits. Added METHOP constructors: - newMETHOP() for method ops with dynamic method names. The only optype for this op is OP_METHOD. - newMETHOP_named() for method ops with constant method names. Optypes for this op are: OP_METHOD_NAMED (currently) and (later) OP_METHOD_SUPER, OP_METHOD_REDIR, OP_METHOD_NEXT, OP_METHOD_NEXTCAN, OP_METHOD_MAYBENEXT (This commit includes fixups by davem) I'll look at trying to fix this, unless someone beats me to it (out for a bit now) Tony * this is simply the first build failure found with -DPERL_OP_PARENT, there may be other op-tree bugs.
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 486b
On Mon Nov 17 17:01:17 2014, tonyc wrote: Show quoted text
> Build failure* bisected to: > > bad - could not build test-prep > b46e009d94293e069270690750f6c669c6d0ce22 is the first bad commit > commit b46e009d94293e069270690750f6c669c6d0ce22 > Author: syber <syber@crazypanda.ru> > Date: Thu Sep 4 22:08:59 2014 +0400
Turns out there were two problems, an earlier commit 2872f9187 didn't add a needed parent link. Patch attached, I'll apply it tomorrow if no-one points out a problem with it. Tony
Subject: 0001-fix-PERL_OP_PARENT-builds.patch
From 22f53d964f94d524ba285bcd7e9a110d97e67821 Mon Sep 17 00:00:00 2001 From: Tony Cook <tony@develop-help.com> Date: Tue, 18 Nov 2014 17:11:58 +1100 Subject: [PATCH] fix PERL_OP_PARENT builds This was broken in two commits: - b46e009d9 - introduced newMETHOP(), which didn't add the parent link as newUNOP() was doing - 2872f9187 - updated ck_sort() to handle lexical subs named as a bareword parameter to sort, but didn't update the parent link in the new PADCV op created. --- op.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/op.c b/op.c index 00c1255..728b927 100644 --- a/op.c +++ b/op.c @@ -4657,6 +4657,11 @@ S_newMETHOP_internal(pTHX_ I32 type, I32 flags, OP* dynamic_meth, SV* const_meth methop->op_flags = (U8)(flags | OPf_KIDS); methop->op_u.op_first = dynamic_meth; methop->op_private = (U8)(1 | (flags >> 8)); + +#ifdef PERL_OP_PARENT + if (!OP_HAS_SIBLING(dynamic_meth)) + dynamic_meth->op_sibling = (OP*)methop; +#endif } else { assert(const_meth); @@ -10649,6 +10654,9 @@ Perl_ck_sort(pTHX_ OP *o) OP * const padop = newOP(OP_PADCV, 0); padop->op_targ = off; cUNOPx(firstkid)->op_first = padop; +#ifdef PERL_OP_PARENT + padop->op_sibling = firstkid; +#endif op_free(kid); } } -- 1.7.10.4
Date: Tue, 18 Nov 2014 10:54:20 +0000
From: Dave Mitchell <davem [...] iabyn.com>
To: Tony Cook via RT <perlbug-followup [...] perl.org>
CC: perl5-porters [...] perl.org
Subject: Re: [perl #108276] C stack overflow in Perl_scalarvoid
Download (untitled) / with headers
text/plain 260b
On Mon, Nov 17, 2014 at 10:15:08PM -0800, Tony Cook via RT wrote: Show quoted text
> Patch attached, I'll apply it tomorrow if no-one points out a problem with it.
Looks good to me, thanks. -- Dave's first rule of Opera: If something needs saying, say it: don't warble it.
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 287b
On Tue Nov 18 02:54:42 2014, davem wrote: Show quoted text
> On Mon, Nov 17, 2014 at 10:15:08PM -0800, Tony Cook via RT wrote:
> > Patch attached, I'll apply it tomorrow if no-one points out a problem > > with it.
> > Looks good to me, thanks.
Applied as 754cffb022550c89c97e60092b1b9af137112f0f. Tony
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 422b
On Mon Nov 17 04:49:05 2014, davem wrote: Show quoted text
> Note that once PERL_OP_PARENT becomes the default in blead, the > recursion > issue in most of the tree-walking functions in op.c will become > trivially > fixable (the last op_sibling in each chain points back to the parent, > so > a tree can be walked without needing to maintain state.)
Something like the attached? Applies on top of the other S_finalize_op() change. Tony
Subject: 0001-perl-108276-use-the-PERL_OP_PARENT-links-in-S_finali.patch
From 9f55fceda22a4ca097bc0a715f58a4dbb8a3aeae Mon Sep 17 00:00:00 2001 From: Tony Cook <tony@develop-help.com> Date: Wed, 19 Nov 2014 14:18:17 +1100 Subject: [perl #108276] use the PERL_OP_PARENT links in S_finalize_op() if possible --- embed.fnc | 3 +++ embed.h | 3 +++ op.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- proto.h | 8 ++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/embed.fnc b/embed.fnc index 77ceca8..67da32a 100644 --- a/embed.fnc +++ b/embed.fnc @@ -910,6 +910,9 @@ poX |OP* |op_lvalue_flags|NULLOK OP* o|I32 type|U32 flags p |void |finalize_optree |NN OP* o #if defined(PERL_IN_OP_C) s |void |finalize_op |NN OP* o +# ifdef PERL_OP_PARENT +s |OP* |traverse_op_tree|NN OP* top|NN OP* o +# endif s |void |move_proto_attr|NN OP **proto|NN OP **attrs|NN const GV *name #endif : Used in op.c and pp_sys.c diff --git a/embed.h b/embed.h index 7fddb5d..b8acf8b 100644 --- a/embed.h +++ b/embed.h @@ -1539,6 +1539,9 @@ #define simplify_sort(a) S_simplify_sort(aTHX_ a) #define too_few_arguments_pv(a,b,c) S_too_few_arguments_pv(aTHX_ a,b,c) #define too_many_arguments_pv(a,b,c) S_too_many_arguments_pv(aTHX_ a,b,c) +# if defined(PERL_OP_PARENT) +#define traverse_op_tree(a,b) S_traverse_op_tree(aTHX_ a,b) +# endif # if defined(USE_ITHREADS) #define op_relocate_sv(a,b) S_op_relocate_sv(aTHX_ a,b) # endif diff --git a/op.c b/op.c index eee542a..6c2482e 100644 --- a/op.c +++ b/op.c @@ -2197,15 +2197,64 @@ S_op_relocate_sv(pTHX_ SV** svp, PADOFFSET* targp) } #endif +#ifdef PERL_OP_PARENT + +/* +=for apidoc s|OP*|traverse_op_tree|OP* top|OP* o + +Return the next op in a depth-first traversal of the op tree, +returning NULL when the traversal is complete. + +The initial call must supply the root of the tree as both top and o. + +This is only available under -DPERL_OP_PARENT. + +For now it's static, but it may be exposed to the API in the future. + +=cut +*/ + +STATIC OP* +S_traverse_op_tree(OP *top, OP *o) { + OP *sib; + + PERL_ARGS_ASSERT_TRAVERSE_OP_TREE; + + if ((o->op_flags & OPf_KIDS) && cUNOPo->op_first) { + return cUNOPo->op_first; + } + else if ((sib = OP_SIBLING(o))) { + return sib; + } + else { + OP *parent = o->op_sibling; + while (parent && parent != top) { + OP *sib = OP_SIBLING(parent); + if (sib) + return sib; + parent = parent->op_sibling; + } + + return NULL; + } +} + +#endif STATIC void S_finalize_op(pTHX_ OP* o) { +#ifdef PERL_OP_PARENT + OP *top = o; +#else DEFER_OP_DECLARE; +#endif PERL_ARGS_ASSERT_FINALIZE_OP; - + /*op_dump(o);*/ + /*PerlIO_printf(PerlIO_stderr(), "entering loop\n");*/ do { + /*PerlIO_printf(PerlIO_stderr(), "op %p (%s) first %p sib %p lastsib %d\n", o, PL_op_name[o->op_type], cUNOPo->op_first, o->op_sibling, o->op_lastsib);*/ switch (o->op_type) { case OP_NEXTSTATE: case OP_DBSTATE: @@ -2430,6 +2479,7 @@ S_finalize_op(pTHX_ OP* o) # endif } #endif +#ifndef PERL_OP_PARENT { /* Count then fill from the top to ensure any diagnostics are produced in order from the start of the code. @@ -2444,10 +2494,19 @@ S_finalize_op(pTHX_ OP* o) for (kid = cUNOPo->op_first; kid; kid = OP_SIBLING(kid)) *--fill = kid; } +#endif } - } while ( (o = POP_DEFERRED_OP()) ); + } while ( +#ifdef PERL_OP_PARENT + (o = S_traverse_op_tree(top, o)) +#else + (o = POP_DEFERRED_OP()) +#endif + ); +#ifndef PERL_OP_PARENT DEFER_OP_END; +#endif } /* diff --git a/proto.h b/proto.h index 656d6b4..d985cee 100644 --- a/proto.h +++ b/proto.h @@ -6366,6 +6366,14 @@ STATIC OP* S_too_many_arguments_pv(pTHX_ OP *o, const char* name, U32 flags) #define PERL_ARGS_ASSERT_TOO_MANY_ARGUMENTS_PV \ assert(o); assert(name) +# if defined(PERL_OP_PARENT) +STATIC OP* S_traverse_op_tree(pTHX_ OP* top, OP* o) + __attribute__nonnull__(pTHX_1) + __attribute__nonnull__(pTHX_2); +#define PERL_ARGS_ASSERT_TRAVERSE_OP_TREE \ + assert(top); assert(o) + +# endif # if defined(USE_ITHREADS) PERL_STATIC_INLINE void S_op_relocate_sv(pTHX_ SV** svp, PADOFFSET* targp) __attribute__nonnull__(pTHX_1) -- 1.7.10.4
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 717b
On Tue Nov 18 19:19:28 2014, tonyc wrote: Show quoted text
> On Mon Nov 17 04:49:05 2014, davem wrote:
> > Note that once PERL_OP_PARENT becomes the default in blead, the > > recursion > > issue in most of the tree-walking functions in op.c will become > > trivially > > fixable (the last op_sibling in each chain points back to the parent, > > so > > a tree can be walked without needing to maintain state.)
> > Something like the attached? > > Applies on top of the other S_finalize_op() change.
Would it be possible to make it even simpler to use? OP *o = whatever; OP *kid; FOR_EACH_OP_DESCENDENT(o, kid) { if (blah blah blah) goto finished; } finished: END_FOR_EACH_OP_DESCENDENT; -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.5k
On Tue Nov 18 21:56:19 2014, sprout wrote: Show quoted text
> On Tue Nov 18 19:19:28 2014, tonyc wrote:
> > On Mon Nov 17 04:49:05 2014, davem wrote:
> > > Note that once PERL_OP_PARENT becomes the default in blead, the > > > recursion > > > issue in most of the tree-walking functions in op.c will become > > > trivially > > > fixable (the last op_sibling in each chain points back to the parent, > > > so > > > a tree can be walked without needing to maintain state.)
> > > > Something like the attached? > > > > Applies on top of the other S_finalize_op() change.
> > Would it be possible to make it even simpler to use? > > OP *o = whatever; > OP *kid; > > FOR_EACH_OP_DESCENDENT(o, kid) { > > if (blah blah blah) goto finished; > > } > finished: > END_FOR_EACH_OP_DESCENDENT;
I'm not sure it's practical. It wouldn't be as simple as you've illustrated. It would be tricky to use with Perl_scalarvoid(), since it doesn't scalarvoid(o) every node in the tree, and would need a mechanism to skip a subtree. op_free() has a similar issue, since it skips already freed child ops and their sub-trees. It's also special in that it needs to store the link to the next node before processing the current node. op_finalize() is special compared to the others too, for op_free() and scalarvoid() it doesn't matter much which direction we iterate over children, but it does for finalize_op(), and it pays a small performance cost with the DEFER_OP() mechanism. A general mechanism would pass that cost onto op_free() and scalarvoid(). Tony


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org