Skip to content

Commit

Permalink
builtin: avoid passing bad parent argument to op_sibling_splice
Browse files Browse the repository at this point in the history
op_sibling_splice() is supposed to be called with a parent/child op pair
as the first two arguments. But in `op_sibling_splice(parent, pushop, 1,
NULL)`, `parent` is not necessarily a parent of `pushop`; it can also
be a grandparent. In practice, this is harmless, however, as the parent
argument is only used when splicing the first or last sibling of an op
chain, which is never the case here (as ensured by the `argop` checks).

So just avoid `parent` altogether and pass `NULL` as the first argument
instead, which is a documented part of the op_sibling_splice() API (and
will raise a proper error if our assumptions don't hold in the future).
  • Loading branch information
mauke committed Dec 30, 2024
1 parent 8f5aa22 commit a73cdae
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,19 +431,21 @@ static OP *ck_builtin_func1(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
if(!opcode)
return entersubop;

OP *parent = entersubop, *pushop, *argop;

pushop = cUNOPx(entersubop)->op_first;
OP *pushop = cUNOPx(entersubop)->op_first;
if (!OpHAS_SIBLING(pushop)) {
pushop = cUNOPx(pushop)->op_first;
}

argop = OpSIBLING(pushop);
OP *argop = OpSIBLING(pushop);

if (!argop || !OpHAS_SIBLING(argop) || OpHAS_SIBLING(OpSIBLING(argop)))
return entersubop;

(void)op_sibling_splice(parent, pushop, 1, NULL);
{
OP *const excised = op_sibling_splice(NULL, pushop, 1, NULL);
PERL_UNUSED_VAR(excised);
assert(excised == argop);
}

U8 wantflags = entersubop->op_flags & OPf_WANT;

Expand Down

0 comments on commit a73cdae

Please sign in to comment.