| 1 | #!./perl |
| 2 | |
| 3 | # Checks if the parser behaves correctly in edge cases |
| 4 | # (including weird syntax errors) |
| 5 | |
| 6 | BEGIN { |
| 7 | @INC = qw(. ../lib); |
| 8 | chdir 't' if -d 't'; |
| 9 | } |
| 10 | |
| 11 | print "1..191\n"; |
| 12 | |
| 13 | sub failed { |
| 14 | my ($got, $expected, $name) = @_; |
| 15 | |
| 16 | print "not ok $test - $name\n"; |
| 17 | my @caller = caller(1); |
| 18 | print "# Failed test at $caller[1] line $caller[2]\n"; |
| 19 | if (defined $got) { |
| 20 | print "# Got '$got'\n"; |
| 21 | } else { |
| 22 | print "# Got undef\n"; |
| 23 | } |
| 24 | print "# Expected $expected\n"; |
| 25 | return; |
| 26 | } |
| 27 | |
| 28 | sub like { |
| 29 | my ($got, $pattern, $name) = @_; |
| 30 | $test = $test + 1; |
| 31 | if (defined $got && $got =~ $pattern) { |
| 32 | print "ok $test - $name\n"; |
| 33 | # Principle of least surprise - maintain the expected interface, even |
| 34 | # though we aren't using it here (yet). |
| 35 | return 1; |
| 36 | } |
| 37 | failed($got, $pattern, $name); |
| 38 | } |
| 39 | |
| 40 | sub is { |
| 41 | my ($got, $expect, $name) = @_; |
| 42 | $test = $test + 1; |
| 43 | if (defined $expect) { |
| 44 | if (defined $got && $got eq $expect) { |
| 45 | print "ok $test - $name\n"; |
| 46 | return 1; |
| 47 | } |
| 48 | failed($got, "'$expect'", $name); |
| 49 | } else { |
| 50 | if (!defined $got) { |
| 51 | print "ok $test - $name\n"; |
| 52 | return 1; |
| 53 | } |
| 54 | failed($got, 'undef', $name); |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | eval '%@x=0;'; |
| 59 | like( $@, qr/^Can't modify hash dereference in repeat \(x\)/, '%@x=0' ); |
| 60 | |
| 61 | # Bug 20010422.005 (#6874) |
| 62 | eval q{{s//${}/; //}}; |
| 63 | like( $@, qr/syntax error/, 'syntax error, used to dump core' ); |
| 64 | |
| 65 | # Bug 20010528.007 (#7052) |
| 66 | eval q/"\x{"/; |
| 67 | like( $@, qr/^Missing right brace on \\x/, |
| 68 | 'syntax error in string, used to dump core' ); |
| 69 | |
| 70 | eval q/"\N{"/; |
| 71 | like( $@, qr/^Missing right brace on \\N/, |
| 72 | 'syntax error in string with incomplete \N' ); |
| 73 | eval q/"\Nfoo"/; |
| 74 | like( $@, qr/^Missing braces on \\N/, |
| 75 | 'syntax error in string with incomplete \N' ); |
| 76 | |
| 77 | eval q/"\o{"/; |
| 78 | like( $@, qr/^Missing right brace on \\o/, |
| 79 | 'syntax error in string with incomplete \o' ); |
| 80 | eval q/"\ofoo"/; |
| 81 | like( $@, qr/^Missing braces on \\o/, |
| 82 | 'syntax error in string with incomplete \o' ); |
| 83 | |
| 84 | eval "a.b.c.d.e.f;sub"; |
| 85 | like( $@, qr/^Illegal declaration of anonymous subroutine/, |
| 86 | 'found by Markov chain stress testing' ); |
| 87 | |
| 88 | # Bug 20010831.001 (#7605) |
| 89 | eval '($a, b) = (1, 2);'; |
| 90 | like( $@, qr/^Can't modify constant item in list assignment/, |
| 91 | 'bareword in list assignment' ); |
| 92 | |
| 93 | eval 'tie FOO, "Foo";'; |
| 94 | like( $@, qr/^Can't modify constant item in tie /, |
| 95 | 'tying a bareword causes a segfault in 5.6.1' ); |
| 96 | |
| 97 | eval 'undef foo'; |
| 98 | like( $@, qr/^Can't modify constant item in undef operator /, |
| 99 | 'undefing constant causes a segfault in 5.6.1 [ID 20010906.019 (#7642)]' ); |
| 100 | |
| 101 | eval 'read($bla, FILE, 1);'; |
| 102 | like( $@, qr/^Can't modify constant item in read /, |
| 103 | 'read($var, FILE, 1) segfaults on 5.6.1 [ID 20011025.054 (#7847)]' ); |
| 104 | |
| 105 | # This used to dump core (bug #17920) |
| 106 | eval q{ sub { sub { f1(f2();); my($a,$b,$c) } } }; |
| 107 | like( $@, qr/error/, 'lexical block discarded by yacc' ); |
| 108 | |
| 109 | # bug #18573, used to corrupt memory |
| 110 | eval q{ "\c" }; |
| 111 | like( $@, qr/^Missing control char name in \\c/, q("\c" string) ); |
| 112 | |
| 113 | eval q{ qq(foo$) }; |
| 114 | like( $@, qr/Final \$ should be \\\$ or \$name/, q($ at end of "" string) ); |
| 115 | |
| 116 | # two tests for memory corruption problems in the said variables |
| 117 | # (used to dump core or produce strange results) |
| 118 | |
| 119 | is( "\Q\Q\Q\Q\Q\Q\Q\Q\Q\Q\Q\Q\Qa", "a", "PL_lex_casestack" ); |
| 120 | |
| 121 | eval { |
| 122 | {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
| 123 | {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
| 124 | {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
| 125 | }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
| 126 | }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
| 127 | }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
| 128 | }; |
| 129 | is( $@, '', 'PL_lex_brackstack' ); |
| 130 | |
| 131 | { |
| 132 | # tests for bug #20716 |
| 133 | undef $a; |
| 134 | undef @b; |
| 135 | my $a="A"; |
| 136 | is("${a}{", "A{", "interpolation, qq//"); |
| 137 | is("${a}[", "A[", "interpolation, qq//"); |
| 138 | my @b=("B"); |
| 139 | is("@{b}{", "B{", "interpolation, qq//"); |
| 140 | is(qr/${a}\{/, '(?^:A\{)', "interpolation, qr//"); |
| 141 | my $c = "A{"; |
| 142 | $c =~ /${a}\{/; |
| 143 | is($&, 'A{', "interpolation, m//"); |
| 144 | $c =~ s/${a}\{/foo/; |
| 145 | is($c, 'foo', "interpolation, s/...//"); |
| 146 | $c =~ s/foo/${a}{/; |
| 147 | is($c, 'A{', "interpolation, s//.../"); |
| 148 | is(<<"${a}{", "A{ A[ B{\n", "interpolation, here doc"); |
| 149 | ${a}{ ${a}[ @{b}{ |
| 150 | ${a}{ |
| 151 | } |
| 152 | |
| 153 | eval q{ sub a(;; &) { } a { } }; |
| 154 | is($@, '', "';&' sub prototype confuses the lexer"); |
| 155 | |
| 156 | # Bug #21575 |
| 157 | # ensure that the second print statement works, by playing a bit |
| 158 | # with the test output. |
| 159 | my %data = ( foo => "\n" ); |
| 160 | print "#"; |
| 161 | print( |
| 162 | $data{foo}); |
| 163 | $test = $test + 1; |
| 164 | print "ok $test\n"; |
| 165 | |
| 166 | # Bug #21875 |
| 167 | # { q.* => ... } should be interpreted as hash, not block |
| 168 | |
| 169 | foreach my $line (split /\n/, <<'EOF') |
| 170 | 1 { foo => 'bar' } |
| 171 | 1 { qoo => 'bar' } |
| 172 | 1 { q => 'bar' } |
| 173 | 1 { qq => 'bar' } |
| 174 | 0 { q,'bar', } |
| 175 | 0 { q=bar= } |
| 176 | 0 { qq=bar= } |
| 177 | 1 { q=bar= => 'bar' } |
| 178 | EOF |
| 179 | { |
| 180 | my ($expect, $eval) = split / /, $line, 2; |
| 181 | my $result = eval $eval; |
| 182 | is($@, '', "eval $eval"); |
| 183 | is(ref $result, $expect ? 'HASH' : '', $eval); |
| 184 | } |
| 185 | |
| 186 | # Bug #24212 |
| 187 | { |
| 188 | local $SIG{__WARN__} = sub { }; # silence mandatory warning |
| 189 | eval q{ my $x = -F 1; }; |
| 190 | like( $@, qr/(?i:syntax|parse) error .* near "F 1"/, "unknown filetest operators" ); |
| 191 | is( |
| 192 | eval q{ sub F { 42 } -F 1 }, |
| 193 | '-42', |
| 194 | '-F calls the F function' |
| 195 | ); |
| 196 | } |
| 197 | |
| 198 | # Bug #24762 |
| 199 | { |
| 200 | eval q{ *foo{CODE} ? 1 : 0 }; |
| 201 | is( $@, '', "glob subscript in conditional" ); |
| 202 | } |
| 203 | |
| 204 | # Bug #25824 |
| 205 | { |
| 206 | eval q{ sub f { @a=@b=@c; {use} } }; |
| 207 | like( $@, qr/syntax error/, "use without body" ); |
| 208 | } |
| 209 | |
| 210 | # [perl #2738] perl segfautls on input |
| 211 | { |
| 212 | eval q{ sub _ <> {} }; |
| 213 | like($@, qr/Illegal declaration of subroutine main::_/, "readline operator as prototype"); |
| 214 | |
| 215 | eval q{ $s = sub <> {} }; |
| 216 | like($@, qr/Illegal declaration of anonymous subroutine/, "readline operator as prototype"); |
| 217 | |
| 218 | eval q{ sub _ __FILE__ {} }; |
| 219 | like($@, qr/Illegal declaration of subroutine main::_/, "__FILE__ as prototype"); |
| 220 | } |
| 221 | |
| 222 | # tests for "Bad name" |
| 223 | eval q{ foo::$bar }; |
| 224 | like( $@, qr/Bad name after foo::/, 'Bad name after foo::' ); |
| 225 | eval q{ foo''bar }; |
| 226 | like( $@, qr/Bad name after foo'/, 'Bad name after foo\'' ); |
| 227 | |
| 228 | # test for ?: context error |
| 229 | eval q{($a ? $x : ($y)) = 5}; |
| 230 | like( $@, qr/Assignment to both a list and a scalar/, 'Assignment to both a list and a scalar' ); |
| 231 | |
| 232 | eval q{ s/x/#/e }; |
| 233 | is( $@, '', 'comments in s///e' ); |
| 234 | |
| 235 | # these five used to coredump because the op cleanup on parse error could |
| 236 | # be to the wrong pad |
| 237 | |
| 238 | eval q[ |
| 239 | sub { our $a= 1;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a; |
| 240 | sub { my $z |
| 241 | ]; |
| 242 | |
| 243 | like($@, qr/Missing right curly/, 'nested sub syntax error' ); |
| 244 | |
| 245 | eval q[ |
| 246 | sub { my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s); |
| 247 | sub { my $z |
| 248 | ]; |
| 249 | like($@, qr/Missing right curly/, 'nested sub syntax error 2' ); |
| 250 | |
| 251 | eval q[ |
| 252 | sub { our $a= 1;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a;$a; |
| 253 | use DieDieDie; |
| 254 | ]; |
| 255 | |
| 256 | like($@, qr/Can't locate DieDieDie.pm/, 'croak cleanup' ); |
| 257 | |
| 258 | eval q[ |
| 259 | sub { my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s); |
| 260 | use DieDieDie; |
| 261 | ]; |
| 262 | |
| 263 | like($@, qr/Can't locate DieDieDie.pm/, 'croak cleanup 2' ); |
| 264 | |
| 265 | |
| 266 | eval q[ |
| 267 | my @a; |
| 268 | my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s); |
| 269 | @a =~ s/a/b/; # compile-time error |
| 270 | use DieDieDie; |
| 271 | ]; |
| 272 | |
| 273 | like($@, qr/Can't modify/, 'croak cleanup 3' ); |
| 274 | |
| 275 | # these might leak, or have duplicate frees, depending on the bugginess of |
| 276 | # the parser stack 'fail in reduce' cleanup code. They're here mainly as |
| 277 | # something to be run under valgrind, with PERL_DESTRUCT_LEVEL=1. |
| 278 | |
| 279 | eval q[ BEGIN { } ] for 1..10; |
| 280 | is($@, "", 'BEGIN 1' ); |
| 281 | |
| 282 | eval q[ BEGIN { my $x; $x = 1 } ] for 1..10; |
| 283 | is($@, "", 'BEGIN 2' ); |
| 284 | |
| 285 | eval q[ BEGIN { \&foo1 } ] for 1..10; |
| 286 | is($@, "", 'BEGIN 3' ); |
| 287 | |
| 288 | eval q[ sub foo2 { } ] for 1..10; |
| 289 | is($@, "", 'BEGIN 4' ); |
| 290 | |
| 291 | eval q[ sub foo3 { my $x; $x=1 } ] for 1..10; |
| 292 | is($@, "", 'BEGIN 5' ); |
| 293 | |
| 294 | eval q[ BEGIN { die } ] for 1..10; |
| 295 | like($@, qr/BEGIN failed--compilation aborted/, 'BEGIN 6' ); |
| 296 | |
| 297 | eval q[ BEGIN {\&foo4; die } ] for 1..10; |
| 298 | like($@, qr/BEGIN failed--compilation aborted/, 'BEGIN 7' ); |
| 299 | |
| 300 | { |
| 301 | # RT #70934 |
| 302 | # check both the specific case in the ticket, and a few other paths into |
| 303 | # S_scan_ident() |
| 304 | # simplify long ids |
| 305 | my $x100 = "x" x 256; |
| 306 | my $xFE = "x" x 254; |
| 307 | my $xFD = "x" x 253; |
| 308 | my $xFC = "x" x 252; |
| 309 | my $xFB = "x" x 251; |
| 310 | |
| 311 | eval qq[ \$#$xFB ]; |
| 312 | is($@, "", "251 character \$# sigil ident ok"); |
| 313 | eval qq[ \$#$xFC ]; |
| 314 | like($@, qr/Identifier too long/, "too long id in \$# sigil ctx"); |
| 315 | |
| 316 | eval qq[ \$$xFB ]; |
| 317 | is($@, "", "251 character \$ sigil ident ok"); |
| 318 | eval qq[ \$$xFC ]; |
| 319 | like($@, qr/Identifier too long/, "too long id in \$ sigil ctx"); |
| 320 | |
| 321 | eval qq[ %$xFB ]; |
| 322 | is($@, "", "251 character % sigil ident ok"); |
| 323 | eval qq[ %$xFC ]; |
| 324 | like($@, qr/Identifier too long/, "too long id in % sigil ctx"); |
| 325 | |
| 326 | eval qq[ \\&$xFB ]; # take a ref since I don't want to call it |
| 327 | is($@, "", "251 character & sigil ident ok"); |
| 328 | eval qq[ \\&$xFC ]; |
| 329 | like($@, qr/Identifier too long/, "too long id in & sigil ctx"); |
| 330 | |
| 331 | eval qq[ *$xFC ]; |
| 332 | is($@, "", "252 character glob ident ok"); |
| 333 | eval qq[ *$xFD ]; |
| 334 | like($@, qr/Identifier too long/, "too long id in glob ctx"); |
| 335 | |
| 336 | eval qq[ for $xFC ]; |
| 337 | like($@, qr/^Missing \$ on loop variable /, |
| 338 | "252 char id ok, but a different error"); |
| 339 | eval qq[ for $xFD; ]; |
| 340 | like($@, qr/^Missing \$ on loop variable /, "too long id in for ctx"); |
| 341 | |
| 342 | # the specific case from the ticket |
| 343 | # however the parsing code in yyl_foreach has now changed |
| 344 | my $x = "x" x 257; |
| 345 | eval qq[ for $x ]; |
| 346 | like($@, qr/^Missing \$ on loop variable /, "too long id ticket case"); |
| 347 | |
| 348 | # as PL_tokenbuf is now PL_parser->tokenbuf, the "buffer overflow" that was |
| 349 | # reported in GH #9993 now corrupts some other part of the parser structure. |
| 350 | # Currently, that seems to be the line number. Hence this test will fail if |
| 351 | # the fix from commit 0b3da58dfdc35079 is reversed. (However, as the later |
| 352 | # commit 61bc22580524a6d9 changed the code (now) in yyl_foreach() from |
| 353 | # scan_ident() to scan_word(), to recreate the problem one needs to apply |
| 354 | # the buggy change to the calculation of the variable `e` in scan_word() |
| 355 | # instead. |
| 356 | |
| 357 | my $x = "x" x 260; |
| 358 | eval qq[ for my $x \$foo ]; |
| 359 | like($@, qr/at \(eval \d+\) line 1[,.]/, "line number is reported correctly"); |
| 360 | } |
| 361 | |
| 362 | { |
| 363 | is(exists &zlonk, '', 'sub not present'); |
| 364 | eval qq[ {sub zlonk} ]; |
| 365 | is($@, '', 'sub declaration followed by a closing curly'); |
| 366 | is(exists &zlonk, 1, 'sub now stubbed'); |
| 367 | is(defined &zlonk, '', 'but no body defined'); |
| 368 | } |
| 369 | |
| 370 | # [perl #113016] CORE::print::foo |
| 371 | sub CORE'print'foo { 43 } # apostrophes intentional; do not tempt fate |
| 372 | sub CORE'foo'bar { 43 } |
| 373 | is CORE::print::foo, 43, 'CORE::print::foo is not CORE::print ::foo'; |
| 374 | is scalar eval "CORE::foo'bar", 43, "CORE::foo'bar is not an error"; |
| 375 | |
| 376 | # bug #71748 |
| 377 | eval q{ |
| 378 | $_ = ""; |
| 379 | s/(.)/ |
| 380 | { |
| 381 | # |
| 382 | }->{$1}; |
| 383 | /e; |
| 384 | 1; |
| 385 | }; |
| 386 | is($@, "", "multiline whitespace inside substitute expression"); |
| 387 | |
| 388 | eval '@A =~ s/a/b/; # compilation error |
| 389 | sub tahi {} |
| 390 | sub rua; |
| 391 | sub toru ($); |
| 392 | sub wha :lvalue; |
| 393 | sub rima ($%&*$&*\$%\*&$%*&) :method; |
| 394 | sub ono :lvalue { die } |
| 395 | sub whitu (_) { die } |
| 396 | sub waru ($;) :method { die } |
| 397 | sub iwa { die } |
| 398 | BEGIN { }'; |
| 399 | is $::{tahi}, undef, 'empty sub decl ignored after compilation error'; |
| 400 | is $::{rua}, undef, 'stub decl ignored after compilation error'; |
| 401 | is $::{toru}, undef, 'stub+proto decl ignored after compilation error'; |
| 402 | is $::{wha}, undef, 'stub+attr decl ignored after compilation error'; |
| 403 | is $::{rima}, undef, 'stub+proto+attr ignored after compilation error'; |
| 404 | is $::{ono}, undef, 'sub decl with attr ignored after compilation error'; |
| 405 | is $::{whitu}, undef, 'sub decl w proto ignored after compilation error'; |
| 406 | is $::{waru}, undef, 'sub w attr+proto ignored after compilation error'; |
| 407 | is $::{iwa}, undef, 'non-empty sub decl ignored after compilation error'; |
| 408 | is *BEGIN{CODE}, undef, 'BEGIN leaves no stub after compilation error'; |
| 409 | |
| 410 | $test = $test + 1; |
| 411 | "ok $test - format inside re-eval" =~ /(?{ |
| 412 | format = |
| 413 | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
| 414 | $_ |
| 415 | . |
| 416 | write |
| 417 | }).*/; |
| 418 | |
| 419 | eval ' |
| 420 | "${; |
| 421 | |
| 422 | =pod |
| 423 | |
| 424 | =cut |
| 425 | |
| 426 | }"; |
| 427 | '; |
| 428 | is $@, "", 'pod inside string in string eval'; |
| 429 | "${; |
| 430 | |
| 431 | =pod |
| 432 | |
| 433 | =cut |
| 434 | |
| 435 | }"; |
| 436 | print "ok ", ++$test, " - pod inside string outside of string eval\n"; |
| 437 | |
| 438 | like "blah blah blah\n", qr/${\ <<END |
| 439 | blah blah blah |
| 440 | END |
| 441 | }/, 'here docs in multiline quoted construct'; |
| 442 | like "blah blah blah\n", eval q|qr/${\ <<END |
| 443 | blah blah blah |
| 444 | END |
| 445 | }/|, 'here docs in multiline quoted construct in string eval'; |
| 446 | |
| 447 | # Unterminated here-docs in subst in eval; used to crash |
| 448 | eval 's/${<<END}//'; |
| 449 | eval 's//${<<END}/'; |
| 450 | print "ok ", ++$test, " - unterminated here-docs in s/// in string eval\n"; |
| 451 | |
| 452 | sub 'Hello'_he_said (_); |
| 453 | is prototype "Hello::_he_said", '_', 'initial tick in sub declaration'; |
| 454 | |
| 455 | { |
| 456 | my @x = 'string'; |
| 457 | is(eval q{ "$x[0]->strung" }, 'string->strung', |
| 458 | 'literal -> after an array subscript within ""'); |
| 459 | @x = ['string']; |
| 460 | # this used to give "string" |
| 461 | like("$x[0]-> [0]", qr/^ARRAY\([^)]*\)-> \[0\]\z/, |
| 462 | 'literal -> [0] after an array subscript within ""'); |
| 463 | } |
| 464 | |
| 465 | eval 'no if $] >= 5.17.4 warnings => "deprecated"'; |
| 466 | is 1,1, ' no crash for "no ... syntax error"'; |
| 467 | |
| 468 | for my $pkg(()){} |
| 469 | $pkg = 3; |
| 470 | is $pkg, 3, '[perl #114942] for my $foo()){} $foo'; |
| 471 | |
| 472 | # Check that format 'Foo still works after removing the hack from |
| 473 | # force_word |
| 474 | $test++; |
| 475 | format 'one = |
| 476 | ok @<< - format 'foo still works |
| 477 | $test |
| 478 | . |
| 479 | { |
| 480 | local $~ = "one"; |
| 481 | write(); |
| 482 | } |
| 483 | |
| 484 | $test++; |
| 485 | format ::two = |
| 486 | ok @<< - format ::foo still works |
| 487 | $test |
| 488 | . |
| 489 | { |
| 490 | local $~ = "two"; |
| 491 | write(); |
| 492 | } |
| 493 | |
| 494 | for(__PACKAGE__) { |
| 495 | eval '$_=42'; |
| 496 | is $_, 'main', '__PACKAGE__ is read-only'; |
| 497 | } |
| 498 | |
| 499 | $file = __FILE__; |
| 500 | BEGIN{ ${"_<".__FILE__} = \1 } |
| 501 | is __FILE__, $file, |
| 502 | 'no __FILE__ corruption when setting CopFILESV to a ref'; |
| 503 | |
| 504 | eval 'Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' |
| 505 | .'oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' |
| 506 | .'oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' |
| 507 | .'oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' |
| 508 | .'oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' |
| 509 | .'ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'; |
| 510 | like $@, "^Identifier too long at ", 'ident buffer overflow'; |
| 511 | |
| 512 | eval 'for my a1b $i (1) {}'; |
| 513 | # ng: 'Missing $ on loop variable' |
| 514 | like $@, "^No such class a1b at ", 'TYPE of my of for statement'; |
| 515 | |
| 516 | eval 'method {} {$_,undef}'; |
| 517 | like $@, qq/^Can't call method "method" on unblessed reference at /, |
| 518 | 'method BLOCK {...} does not try to disambiguate'; |
| 519 | |
| 520 | eval '#line 1 maggapom |
| 521 | if ($a>3) { $a ++; } |
| 522 | else {printf(1/0);}'; |
| 523 | is $@, "Illegal division by zero at maggapom line 2.\n", |
| 524 | 'else {foo} line number (no space after {) [perl #122695]'; |
| 525 | |
| 526 | # parentheses needed for this to fail an assertion in S_maybe_multideref |
| 527 | is +(${[{a=>214}]}[0])->{a}, 214, '($array[...])->{...}'; |
| 528 | |
| 529 | # This used to fail an assertion because of the OPf_SPECIAL flag on an |
| 530 | # OP_GV that started out as an OP_CONST. |
| 531 | |
| 532 | sub FILE1 () { 1 } |
| 533 | sub dummy { tell FILE1 } |
| 534 | |
| 535 | # More potential multideref assertion failures |
| 536 | # OPf_PARENS on OP_RV2SV in subscript |
| 537 | $x[($_)]; |
| 538 | is(1,1, "PASS: Previous line successfully parsed. OPf_PARENS on OP_RV2SV"); |
| 539 | # OPf_SPECIAL on OP_GV in subscript |
| 540 | $x[FILE1->[0]]; |
| 541 | is(1,1, "PASS: Previous line successfully parsed. OPf_SPECIAL on OP_GV"); |
| 542 | |
| 543 | # Used to crash [perl #123542] |
| 544 | eval 's /${<>{}) //'; |
| 545 | |
| 546 | # Also used to crash [perl #123652] |
| 547 | eval{$1=eval{a:}}; |
| 548 | |
| 549 | # Used to fail assertions [perl #123753] |
| 550 | eval "map+map"; |
| 551 | eval "grep+grep"; |
| 552 | |
| 553 | # ALso failed an assertion [perl #123848] |
| 554 | { |
| 555 | local $SIG{__WARN__} = sub{}; |
| 556 | eval 'my $_; m// ~~ 0'; |
| 557 | } |
| 558 | |
| 559 | # Used to crash [perl #125679] |
| 560 | eval 'BEGIN {$^H=-1} \eval=time'; |
| 561 | |
| 562 | # Used to fail an assertion [perl #129073] |
| 563 | { |
| 564 | local $SIG{__WARN__} = sub{}; |
| 565 | eval '${p{};sub p}()'; |
| 566 | } |
| 567 | |
| 568 | # RT #124207 syntax error during stringify can leave stringify op |
| 569 | # with multiple children and assertion failures |
| 570 | |
| 571 | eval 'qq{@{0]}${}},{})'; |
| 572 | is(1, 1, "RT #124207"); |
| 573 | |
| 574 | # RT #127993 version control conflict markers |
| 575 | " this should keep working |
| 576 | <<<<<<< |
| 577 | " =~ / |
| 578 | >>>>>>> |
| 579 | /; |
| 580 | for my $marker (qw( |
| 581 | <<<<<<< |
| 582 | ======= |
| 583 | >>>>>>> |
| 584 | )) { |
| 585 | eval "$marker"; |
| 586 | like $@, qr/^Version control conflict marker at \(eval \d+\) line 1, near "$marker"/, "VCS marker '$marker' at beginning"; |
| 587 | eval "\$_\n$marker"; |
| 588 | like $@, qr/^Version control conflict marker at \(eval \d+\) line 2, near "$marker"/, "VCS marker '$marker' after value"; |
| 589 | eval "\n\$_ =\n$marker"; |
| 590 | like $@, qr/^Version control conflict marker at \(eval \d+\) line 3, near "$marker"/, "VCS marker '$marker' after operator"; |
| 591 | } |
| 592 | |
| 593 | # keys assignments in weird contexts (mentioned in perl #128260) |
| 594 | eval 'keys(%h) .= "00"'; |
| 595 | is $@, "", 'keys .='; |
| 596 | eval 'sub { read $fh, keys %h, 0 }'; |
| 597 | is $@, "", 'read into keys'; |
| 598 | eval 'substr keys(%h),0,=3'; |
| 599 | is $@, "", 'substr keys assignment'; |
| 600 | |
| 601 | { # very large utf8 char in error message was overflowing buffer |
| 602 | if (length sprintf("%x", ~0) <= 8) { |
| 603 | is 1, 1, "skip because overflows on 32-bit machine"; |
| 604 | } |
| 605 | else { |
| 606 | no warnings; |
| 607 | eval "q" . chr(100000000064); |
| 608 | like $@, qr/Can't find string terminator "." anywhere before EOF/, |
| 609 | 'RT 128952'; |
| 610 | } |
| 611 | } |
| 612 | |
| 613 | # RT #130311: many parser shifts before a reduce |
| 614 | |
| 615 | { |
| 616 | eval '[' . ('{' x 300); |
| 617 | like $@, qr/Missing right curly or square bracket/, 'RT #130311'; |
| 618 | } |
| 619 | |
| 620 | # RT #130815: crash in ck_return for malformed code |
| 621 | { |
| 622 | eval 'm(@{if(0){sub d{]]])}return'; |
| 623 | like $@, qr/^syntax error at \(eval \d+\) line 1, near "\{\]"/, |
| 624 | 'RT #130815: null pointer deref'; |
| 625 | } |
| 626 | |
| 627 | # Add new tests HERE (above this line) |
| 628 | |
| 629 | # bug #74022: Loop on characters in \p{OtherIDContinue} |
| 630 | # This test hangs if it fails. |
| 631 | eval chr 0x387; # forces loading of utf8.pm |
| 632 | is(1,1, '[perl #74022] Parser looping on OtherIDContinue chars'); |
| 633 | |
| 634 | # More awkward tests for #line. Keep these at the end, as they will screw |
| 635 | # with sane line reporting for any other test failures |
| 636 | |
| 637 | sub check ($$$) { |
| 638 | my ($file, $line, $name) = @_; |
| 639 | my (undef, $got_file, $got_line) = caller; |
| 640 | like ($got_file, $file, "file of $name"); |
| 641 | is ($got_line, $line, "line of $name"); |
| 642 | } |
| 643 | |
| 644 | my $this_file = qr/parser\.t(?:\.[bl]eb?)?$/; |
| 645 | #line 3 |
| 646 | 1 unless |
| 647 | 1; |
| 648 | check($this_file, 5, "[perl #118931]"); |
| 649 | |
| 650 | #line 3 |
| 651 | check($this_file, 3, "bare line"); |
| 652 | |
| 653 | # line 5 |
| 654 | check($this_file, 5, "bare line with leading space"); |
| 655 | |
| 656 | #line 7 |
| 657 | check($this_file, 7, "trailing space still valid"); |
| 658 | |
| 659 | # line 11 |
| 660 | check($this_file, 11, "leading and trailing"); |
| 661 | |
| 662 | # line 13 |
| 663 | check($this_file, 13, "leading tab"); |
| 664 | |
| 665 | #line 17 |
| 666 | check($this_file, 17, "middle tab"); |
| 667 | |
| 668 | #line 19 |
| 669 | check($this_file, 19, "loadsaspaces"); |
| 670 | |
| 671 | #line 23 KASHPRITZA |
| 672 | check(qr/^KASHPRITZA$/, 23, "bare filename"); |
| 673 | |
| 674 | #line 29 "KAHEEEE" |
| 675 | check(qr/^KAHEEEE$/, 29, "filename in quotes"); |
| 676 | |
| 677 | #line 31 "CLINK CLOINK BZZT" |
| 678 | check(qr/^CLINK CLOINK BZZT$/, 31, "filename with spaces in quotes"); |
| 679 | |
| 680 | #line 37 "THOOM THOOM" |
| 681 | check(qr/^THOOM THOOM$/, 37, "filename with tabs in quotes"); |
| 682 | |
| 683 | #line 41 "GLINK PLINK GLUNK DINK" |
| 684 | check(qr/^GLINK PLINK GLUNK DINK$/, 41, "a space after the quotes"); |
| 685 | |
| 686 | #line 43 "BBFRPRAFPGHPP |
| 687 | check(qr/^"BBFRPRAFPGHPP$/, 43, "actually missing a quote is still valid"); |
| 688 | |
| 689 | #line 47 bang eth |
| 690 | check(qr/^"BBFRPRAFPGHPP$/, 46, "but spaces aren't allowed without quotes"); |
| 691 | |
| 692 | #line 77sevenseven |
| 693 | check(qr/^"BBFRPRAFPGHPP$/, 49, "need a space after the line number"); |
| 694 | |
| 695 | eval <<'EOSTANZA'; die $@ if $@; |
| 696 | #line 51 "With wonderful deathless ditties|We build up the world's great cities,|And out of a fabulous story|We fashion an empire's glory:|One man with a dream, at pleasure,|Shall go forth and conquer a crown;|And three with a new song's measure|Can trample a kingdom down." |
| 697 | check(qr/^With.*down\.$/, 51, "Overflow the second small buffer check"); |
| 698 | EOSTANZA |
| 699 | |
| 700 | # And now, turn on the debugger flag for long names |
| 701 | $^P = 0x100; |
| 702 | |
| 703 | #line 53 "For we are afar with the dawning|And the suns that are not yet high,|And out of the infinite morning|Intrepid you hear us cry-|How, spite of your human scorning,|Once more God's future draws nigh,|And already goes forth the warning|That ye of the past must die." |
| 704 | check(qr/^For we.*must die\.$/, 53, "Our long line is set up"); |
| 705 | |
| 706 | eval <<'EOT'; die $@ if $@; |
| 707 | #line 59 " " |
| 708 | check(qr/^ $/, 59, "Overflow the first small buffer check only"); |
| 709 | EOT |
| 710 | |
| 711 | eval <<'EOSTANZA'; die $@ if $@; |
| 712 | #line 61 "Great hail! we cry to the comers|From the dazzling unknown shore;|Bring us hither your sun and your summers;|And renew our world as of yore;|You shall teach us your song's new numbers,|And things that we dreamed not before:|Yea, in spite of a dreamer who slumbers,|And a singer who sings no more." |
| 713 | check(qr/^Great hail!.*no more\.$/, 61, "Overflow both small buffer checks"); |
| 714 | EOSTANZA |
| 715 | |
| 716 | sub check_line ($$) { |
| 717 | my ($line, $name) = @_; |
| 718 | my (undef, undef, $got_line) = caller; |
| 719 | is ($got_line, $line, $name); |
| 720 | } |
| 721 | |
| 722 | #line 531 parser.t |
| 723 | <<EOU; check_line(531, 'on same line as heredoc'); |
| 724 | EOU |
| 725 | s//<<EOV/e if 0; |
| 726 | EOV |
| 727 | check_line(535, 'after here-doc in quotes'); |
| 728 | <<EOW; <<EOX; |
| 729 | ${check_line(537, 'first line of interp in here-doc');; |
| 730 | check_line(538, 'second line of interp in here-doc');} |
| 731 | EOW |
| 732 | ${check_line(540, 'first line of interp in second here-doc on same line');; |
| 733 | check_line(541, 'second line of interp in second heredoc on same line');} |
| 734 | EOX |
| 735 | eval <<'EVAL'; |
| 736 | #line 545 |
| 737 | "${<<EOY; <<EOZ}"; |
| 738 | ${check_line(546, 'first line of interp in here-doc in quotes in eval');; |
| 739 | check_line(547, 'second line of interp in here-doc in quotes in eval');} |
| 740 | EOY |
| 741 | ${check_line(549, '1st line of interp in 2nd hd, same line in q in eval');; |
| 742 | check_line(550, '2nd line of interp in 2nd hd, same line in q in eval');} |
| 743 | EOZ |
| 744 | EVAL |
| 745 | |
| 746 | time |
| 747 | #line 42 |
| 748 | ;check_line(42, 'line number after "nullary\n#line"'); |
| 749 | |
| 750 | "${ |
| 751 | #line 53 |
| 752 | _}"; |
| 753 | check_line(54, 'line number after qq"${#line}"'); |
| 754 | |
| 755 | #line 24 |
| 756 | " |
| 757 | ${check_line(25, 'line number inside qq/<newline>${...}/')}"; |
| 758 | |
| 759 | <<"END"; |
| 760 | ${; |
| 761 | #line 625 |
| 762 | } |
| 763 | END |
| 764 | check_line(627, 'line number after heredoc containing #line'); |
| 765 | |
| 766 | #line 638 |
| 767 | <<ENE . ${ |
| 768 | |
| 769 | ENE |
| 770 | "bar"}; |
| 771 | check_line(642, 'line number after ${expr} surrounding heredoc body'); |
| 772 | |
| 773 | |
| 774 | __END__ |
| 775 | # Don't add new tests HERE. See "Add new tests HERE" above. |