summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-07-14 06:41:30 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-07-14 17:35:31 -0700
commitc650d6974333f05db3de6fe88357fb0e710220a3 (patch)
treec9f9cd0723b68ee3611e4b0ed44ba0bf88454629
parent3be135d8cfe01725ff3bdfcc1b4a30206a1e0ed2 (diff)
downloadperl-c650d6974333f05db3de6fe88357fb0e710220a3.tar.gz
op.c: Further simplify ck_sort
This code currently chases op_next pointers in the sort block to make sure there is none that can point outside. To avoid getting stuck in loops, it has to check for those explicitly. Instead of nulling out any op_next pointer that points to the leave op, we can simply turn the leave into a null op (which we already do) and have the leave op’s op_next pointer point to nothing. That produces the same result in the end: Execution of the sort block is prevented from running rampant and escaping out of it, but exits the runloop instead, returning control to pp_sort.
-rw-r--r--op.c21
1 files changed, 3 insertions, 18 deletions
diff --git a/op.c b/op.c
index aa12ef9381..211ffb208c 100644
--- a/op.c
+++ b/op.c
@@ -9177,25 +9177,10 @@ Perl_ck_sort(pTHX_ OP *o)
if (kid->op_type == OP_SCOPE || kid->op_type == OP_LEAVE) {
LINKLIST(kid);
- if (kid->op_type == OP_SCOPE) {
- kid->op_next = 0;
- }
- else if (kid->op_type == OP_LEAVE) {
- OP *k;
+ if (kid->op_type == OP_LEAVE)
op_null(kid); /* wipe out leave */
- kid->op_next = kid;
-
- for (k = kLISTOP->op_first->op_next; k; k = k->op_next) {
- if (k->op_next == kid)
- k->op_next = 0;
- /* don't descend into loops */
- else if (k->op_type == OP_ENTERLOOP
- || k->op_type == OP_ENTERITER)
- {
- k = cLOOPx(k)->op_lastop;
- }
- }
- }
+ /* Prevent execution from escaping out of the sort block. */
+ kid->op_next = 0;
/* provide scalar context for comparison function/block */
kid = scalar(firstkid);