|
8 | 8 |
|
9 | 9 | use strict qw(refs subs); |
10 | 10 |
|
11 | | -plan(257); |
| 11 | +plan(265); |
12 | 12 |
|
13 | 13 | # Test this first before we extend the stack with other operations. |
14 | 14 | # This caused an asan failure due to a bad write past the end of the stack. |
|
913 | 913 | 'rt#130861: heap uaf in pp_rv2sv'); |
914 | 914 | } |
915 | 915 |
|
| 916 | +# GH 18669 |
| 917 | +# The correct autovivification lvalue ref context should be propagated to |
| 918 | +# both branches of a ?:. So in something like: |
| 919 | +# @{ $cond ? $h{a} : $h{b} } = ...; |
| 920 | +# the helem ops on *both* sides of the conditional should get the DREFAV |
| 921 | +# flag set, indicating that if the hash element doesn't exist, it should |
| 922 | +# be autovivified as an *array ref*. |
| 923 | +# |
| 924 | + |
| 925 | +{ |
| 926 | + my $x = { arr => undef }; |
| 927 | + eval { |
| 928 | + push(@{ $x->{ decide } ? $x->{ not_here } : $x->{ new } }, "mana"); |
| 929 | + }; |
| 930 | + |
| 931 | + is($@, "", "GH 18669: push on non-existent hash ref entry: no errors"); |
| 932 | + is(eval {$x->{new}[0] }, 'mana', |
| 933 | + "GH 18669: push on non-existent hash ref entry: autovivifies" |
| 934 | + ); |
| 935 | + |
| 936 | + $x = { arr => undef }; |
| 937 | + eval { |
| 938 | + push(@{ $x->{ decide } ? $x->{ not_here } : $x->{ arr } }, "mana"); |
| 939 | + }; |
| 940 | + |
| 941 | + is($@, "", "GH 18669: push on undef hash ref entry: no errors"); |
| 942 | + is(eval { $x->{arr}[0] }, 'mana', |
| 943 | + "GH 18669: push on undef hash ref entry: autovivifies" |
| 944 | + ); |
| 945 | + |
| 946 | + # try both branches |
| 947 | + for my $cond (0, 1) { |
| 948 | + my %h; |
| 949 | + eval { @{ $cond ? $h{p} : $h{q} } = 99; }; |
| 950 | + is($@, "", "GH 18669: array assign on $cond cond: no errors"); |
| 951 | + is($h{$cond ? 'p' : 'q'}[0], 99, |
| 952 | + "GH 18669: array assign on $cond cond: autovivifies" |
| 953 | + ); |
| 954 | + } |
| 955 | +} |
| 956 | + |
916 | 957 | # Bit of a hack to make test.pl happy. There are 3 more tests after it leaves. |
917 | 958 | $test = curr_test(); |
918 | 959 | curr_test($test + 3); |
|
0 commit comments