This is a follow-up to
79409ac8, which propagated substr’s own lvalue
context to the first argument only if it was one that would not croak
at compile time.
We can’t propagate OP_REFGEN lvalue context to the first argument,
as it causes the same bug for which #128260 was originally reported;
namely, that it prevents a hash or array from being flattened, causing
an unflattened aggregate to follow code paths that expect only sca-
lars, resulting in assertion failures:
$ ./perl -Ilib -e '%h=1..100; print ${\substr %h, 0}'
Assertion failed: (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV && SvTYPE(sv) != SVt_PVFM), function Perl_sv_2pv_flags, file sv.c, line 2924.
Abort trap: 6
$ ./perl -Ilib -e '@h=1..100; print ${\vec @a, 0, 1}'
Assertion failed: (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVHV && SvTYPE(sv) != SVt_PVFM), function Perl_sv_2pv_flags, file sv.c, line 2924.
Abort trap: 6
if (o->op_flags & OPf_KIDS && OpHAS_SIBLING(cBINOPo->op_first)) {
/* substr and vec */
/* If this op is in merely potential (non-fatal) modifiable
- context, then propagate that context to the kid op. Other-
+ context, then apply OP_ENTERSUB context to
+ the kid op (to avoid croaking). Other-
wise pass this op’s own type so the correct op is mentioned
in error messages. */
op_lvalue(OpSIBLING(cBINOPo->op_first),
- S_potential_mod_type(type) ? type : o->op_type);
+ S_potential_mod_type(type)
+ ? OP_ENTERSUB
+ : o->op_type);
}
break;
}
};
-plan(388);
+plan(390);
run_tests() unless caller;
# [perl #7678] core dump with substr reference and localisation
{$b="abcde"; local $k; *k=\substr($b, 2, 1);}
+# [perl #128260] assertion failure with \substr %h, \substr @h
+{
+ my %h = 1..100;
+ my @a = 1..100;
+ is ${\substr %h, 0}, scalar %h, '\substr %h';
+ is ${\substr @a, 0}, scalar @a, '\substr @a';
+}
+
} # sub run_tests - put tests above this line that can run in threads
set_up_inc('../lib');
}
-plan( tests => 35 );
+plan( tests => 37 );
is(vec($foo,0,1), 0);
$v = vec($x, 0, 8);
is($v, 255, "downgraded utf8 try 2");
}
+
+# [perl #128260] assertion failure with \vec %h, \vec @h
+{
+ my %h = 1..100;
+ my @a = 1..100;
+ is ${\vec %h, 0, 1}, vec(scalar %h, 0, 1), '\vec %h';
+ is ${\vec @a, 0, 1}, vec(scalar @a, 0, 1), '\vec @a';
+}