Skip to content

Commit a73cdae

Browse files
committed
builtin: avoid passing bad parent argument to op_sibling_splice
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).
1 parent 8f5aa22 commit a73cdae

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

builtin.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -431,19 +431,21 @@ static OP *ck_builtin_func1(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
431431
if(!opcode)
432432
return entersubop;
433433

434-
OP *parent = entersubop, *pushop, *argop;
435-
436-
pushop = cUNOPx(entersubop)->op_first;
434+
OP *pushop = cUNOPx(entersubop)->op_first;
437435
if (!OpHAS_SIBLING(pushop)) {
438436
pushop = cUNOPx(pushop)->op_first;
439437
}
440438

441-
argop = OpSIBLING(pushop);
439+
OP *argop = OpSIBLING(pushop);
442440

443441
if (!argop || !OpHAS_SIBLING(argop) || OpHAS_SIBLING(OpSIBLING(argop)))
444442
return entersubop;
445443

446-
(void)op_sibling_splice(parent, pushop, 1, NULL);
444+
{
445+
OP *const excised = op_sibling_splice(NULL, pushop, 1, NULL);
446+
PERL_UNUSED_VAR(excised);
447+
assert(excised == argop);
448+
}
447449

448450
U8 wantflags = entersubop->op_flags & OPf_WANT;
449451

0 commit comments

Comments
 (0)