-
Notifications
You must be signed in to change notification settings - Fork 558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Segfault (stack overflow?) while fuzzing Perl 5.21.8 #14421
Comments
From @geeknikGood afternoon, I'm still fuzzing Perl 5.21.8, built from git source on 14 CC=/path/to/afl-gcc ./Configure I did not use AFL_HARDEN=1 when I ran make, and I also compiled a second geeknik@deb7fuzz:~/findings/perl5/fuzzer03/crashes$ Bareword found where operator expected at geeknik@deb7fuzz:~/findings/perl5/fuzzer03/crashes$ valgrind -q geeknik@deb7fuzz:~/findings/perl5/fuzzer03/crashes$ gdb warning: Can't read pathname for load map: Input/output error. |
From @hvdsA perl built with debugging gives: % ./perl test.pl Here's a shorter testcase (which doesn't clarify much): % cat test.pl We seem to have a PL_lex_repl with PL_lex_inwhat == OP_MATCH, which clearly Hugo |
The RT System itself - Status changed from 'new' to 'open' |
From @cpansproutOn Sat Jan 17 17:09:43 2015, hv wrote:
This is no doubt related to my two favourite japhs: s||${s/.*/|; "${;s/.*/Just an"; I don’t remember exactly how they work. At the time I wrote them I based them on the interesting implementation details I saw in toke.c, which had something to do with PL_sublex_info.sub_inwhat. -- Father Chrysostomos |
From @cpansproutOn Sat Jan 24 22:08:15 2015, sprout wrote:
skipspace() in toke.c, which is usually used to skip whitespace between tokens, reads more input from the file if it needs to. But it checks first to see whether we are in a multiline construct and does not read more input if we are. scan_str, which looks for the final delimiter of the string, does not check whether we are in a multiline construct, but just reads straight ahead. So in this japh: s||${s/.*/|; When the replacement part of the outer s||| is parsed, ‘${s/.*/’ is the current ‘line’ of input, and scan_str, trying to find the final delimiter for the s///, reads the next line of input from the stream, which is ‘/s}Just another Perl hacker,’. It finds its delimiter (and the /s flag to boot) immediately. Then the inner s/// construct is exited via S_sublex_done, which sets PL_sublex_info.sub_inwhat to 0 indiscriminately, even though we are still inside the outer string-like construct. PL_sublex_info.sub_inwhat is what skipspace checks before reading more input. That’s as far as my investigation has reached. I may not continue for another week. -- Father Chrysostomos |
From @cpansproutOn Sat Jan 24 22:44:36 2015, sprout wrote:
The setting of PL_sublex_info.sub_inwhat to 0 prematurely does not appear to be involved in this particular case. The current line of input, which is assumed to be the replacement part of the substitution, now contains ‘Just another Perl hacker,’, which is parsed as part of the s||...| and then parsing continues after that. So s||${s/.*/|; ends up equivalent to s||${s/.*/ (The purpose of that discourse was to refresh my memory of how this stuff works.) Now, for the reduced crashing case: "$a{m/""$b When parsing the initial "$a{m/" string, we find m/.../ inside it, and, again, scan_str reads the next line of input (‘/ m ss’), which is assumed to be inside the first string. Notice that we have no } on the second line, so I assume the setting of sub_inwhat to 0 has some role here, but I do not yet see how PL_lex_repl gets set. (The assertion fails because PL_lex_repl is set when we are inside a match op.) -- Father Chrysostomos |
From @cpansproutOn Sun Feb 01 07:54:28 2015, sprout wrote:
At this point, m ss is read as another match op. So the parser sees stringify ( $a{ PMFUNC ( "" ) PMFUNC and immediately reports this as a syntax error, before we even enter the scope for parsing the inside of m ss. The content of m ss (the empty string) is still inside PL_lex_stuff. The parser, on encountering the syntax error, pops the savestack in the process of popping tokens, thereby exiting the quote-parsing scope. So we end up back at line 1 with ‘"$b’ as the next thing to be read. However, PL_lex_stuff is not localised, so it does not get cleared in this process, but remains set. (Usually PL_lex_stuff does not need to be localised, since it is a temporary value that is set when the string is scanned and then read after the next token has been emitted.) So here we have a string to parse, but PL_lex_stuff is already set, so the string inside "$b<newline>" gets stuffed into PL_sublex_info.repl. The '"'-handling code in yylex then checks PL_lex_stuff to see whether it needs to do double-quote handling. Since PL_lex_stuff contains the empty string from m ss it concludes that this is simply a "" constant, which gets emitted. We continue parsing line 3, till we get to the /x/, which requires an inner quote-handling scope. ‘x’ is written to PL_lex_stuff. PL_sublex_info.repl is still set from before ("$b\n"), which is placed in PL_lex_repl, so when we finish handling the pattern, S_sublex_done sees that there is a replacement still, which fails an assertion because a match cannot have a replacement part. Knowing this much, I can reduce it further, and we can trigger the bug even without the "$a{/" hack, which means we have (at least) two separate bugs here: $ ./miniperl -e '"$a{ 1 m// }"; //' Localising PL_lex_stuff will probably fix this last example. -- Father Chrysostomos |
From @cpansproutI have fixed the crash in eabab8b. The oddity with nested quote-like operators overlapping I have left for now, since it is necessary to track down another bug, and it is harmless. -- Father Chrysostomos |
@cpansprout - Status changed from 'open' to 'pending release' |
From @khwilliamsonThanks for submitting this ticket The issue should be resolved with the release today of Perl v5.22, available at http://www.perl.org/get.html -- |
@khwilliamson - Status changed from 'pending release' to 'resolved' |
Migrated from rt.perl.org#123617 (status was 'resolved')
Searchable as RT123617$
The text was updated successfully, but these errors were encountered: