summaryrefslogtreecommitdiff
path: root/ext/XS-APItest
diff options
context:
space:
mode:
authorIvan Baidakou <the.dmol@yandex.by>2020-06-11 18:33:17 +0300
committerNicolas R <nicolas@atoomic.org>2020-07-30 17:26:35 -0600
commit39f7bd8a2ff37752c0185988072790ef11e92424 (patch)
tree8a0f5d1896b8007c70a03033add78049cdd87b36 /ext/XS-APItest
parentf4941eebb5185b70b980fcfea9f7b02f377f1f70 (diff)
downloadperl-39f7bd8a2ff37752c0185988072790ef11e92424.tar.gz
Correct my_rpeep example in perlguts
The example of my_rpeep in perlguts has an issue that it might never stop iterating if there is a cycle in OP tree. For example in the repository https://github.com/basiliscos/p5-PeepholeTest it hangs when starts executing test.pl The right traversal was originally taken from https://metacpan.org/source/ZEFRAM/Devel-GoFaster-0.001/lib/Devel/GoFaster.xs#L330
Diffstat (limited to 'ext/XS-APItest')
-rw-r--r--ext/XS-APItest/APItest.xs13
1 files changed, 9 insertions, 4 deletions
diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs
index 5848abce54..cf3285b5ff 100644
--- a/ext/XS-APItest/APItest.xs
+++ b/ext/XS-APItest/APItest.xs
@@ -470,19 +470,24 @@ my_peep (pTHX_ OP *o)
}
STATIC void
-my_rpeep (pTHX_ OP *o)
+my_rpeep (pTHX_ OP *first)
{
dMY_CXT;
- if (!o)
+ if (!first)
return;
- MY_CXT.orig_rpeep(aTHX_ o);
+ MY_CXT.orig_rpeep(aTHX_ first);
if (!MY_CXT.peep_recording)
return;
- for (; o; o = o->op_next) {
+ for (OP *o = first, *t = first; o; o = o->op_next, t = t->op_next) {
+ if (o->op_type == OP_CONST && cSVOPx_sv(o) && SvPOK(cSVOPx_sv(o))) {
+ av_push(MY_CXT.rpeep_recorder, newSVsv(cSVOPx_sv(o)));
+ }
+ o = o->op_next;
+ if (!o || o == t) break;
if (o->op_type == OP_CONST && cSVOPx_sv(o) && SvPOK(cSVOPx_sv(o))) {
av_push(MY_CXT.rpeep_recorder, newSVsv(cSVOPx_sv(o)));
}