Skip to content

Commit

Permalink
fix "uninitialized value" warnings for shift()/pop()
Browse files Browse the repository at this point in the history
This fixes an oversight introduced in 1b0ae12.

The Perl code "shift" (or "shift()") produces different optrees
depending on where it occurs: At file scope, it shifts @argv and the
corresponding OP has an explicit @argv child. But at subroutine scope,
it shifts @_, and @_ is not represented explicitly in the optree.
Instead the parser just generates an OP_SHIFT without any children.

This latter case was not handled in S_find_uninit_var (and blindly
accessing a non-existent child OP would crash perl). pop() was similarly
affected.

Fix: Explicitly check whether OPf_KIDS is set on the OP before accessing
the op_first field (plus some tests for this case).

Fixes Perl#21960.
  • Loading branch information
mauke committed Feb 9, 2024
1 parent 495831c commit 231916f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 16 deletions.
36 changes: 20 additions & 16 deletions sv.c
Original file line number Diff line number Diff line change
Expand Up @@ -17506,32 +17506,36 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
if (match) {
break;
}
o = cUNOPx(obase)->op_first;
if (o->op_type == OP_RV2AV) {
o2 = cUNOPx(o)->op_first;
if (o2->op_type != OP_GV) {
break;
if (!(obase->op_flags & OPf_KIDS)) {
sv = newSVpvn_flags("", 0, SVs_TEMP);
}
else {
o = cUNOPx(obase)->op_first;
if (o->op_type == OP_RV2AV) {
o2 = cUNOPx(o)->op_first;
if (o2->op_type != OP_GV) {
break;
}
gv = cGVOPx_gv(o2);
if (!gv) {
break;
}
}
else if (o->op_type == OP_PADAV) {
gv = NULL;
}
gv = cGVOPx_gv(o2);
if (!gv) {
else {
break;
}
sv = varname(gv, '@', o->op_targ, NULL, 0, FUV_SUBSCRIPT_NONE);
}
else if (o->op_type == OP_PADAV) {
gv = NULL;
}
else {
break;
}
sv = varname(gv, '@', o->op_targ, NULL, 0, FUV_SUBSCRIPT_NONE);
if (sv) {
const char *name = OP_NAME(obase);
Perl_sv_insert_flags(aTHX_ sv, 0, 0, STR_WITH_LEN("("), 0);
Perl_sv_insert_flags(aTHX_ sv, 0, 0, name, strlen(name), 0);
sv_catpvs_nomg(sv, ")");
return sv;
}
break;
return sv;

case OP_POS:
/* def-ness of rval pos() is independent of the def-ness of its arg */
Expand Down
10 changes: 10 additions & 0 deletions t/lib/warnings/9uninit
Original file line number Diff line number Diff line change
Expand Up @@ -2277,6 +2277,12 @@ $_ = length shift @$ref == 0;
$_ = length pop @$ref == 0;

$_ = splice(@arr, 0, 0) == 0;

# GH #21960
$_ = lc shift;
$_ = sub { lc shift }->();
$_ = lc pop;
$_ = sub { lc pop }->();
EXPECT
Use of uninitialized value in numeric eq (==) at - line 6.
Use of uninitialized value length($x) in numeric eq (==) at - line 7.
Expand All @@ -2292,3 +2298,7 @@ Use of uninitialized value length(pop(@arr)) in numeric eq (==) at - line 19.
Use of uninitialized value in numeric eq (==) at - line 20.
Use of uninitialized value in numeric eq (==) at - line 21.
Use of uninitialized value in numeric eq (==) at - line 23.
Use of uninitialized value shift(@ARGV) in lc at - line 26.
Use of uninitialized value shift() in lc at - line 27.
Use of uninitialized value pop(@ARGV) in lc at - line 28.
Use of uninitialized value pop() in lc at - line 29.

0 comments on commit 231916f

Please sign in to comment.