diff options
author | Ivan Baidakou <the.dmol@yandex.by> | 2020-06-11 18:33:17 +0300 |
---|---|---|
committer | Nicolas R <nicolas@atoomic.org> | 2020-07-30 17:26:35 -0600 |
commit | 39f7bd8a2ff37752c0185988072790ef11e92424 (patch) | |
tree | 8a0f5d1896b8007c70a03033add78049cdd87b36 /ext/XS-APItest | |
parent | f4941eebb5185b70b980fcfea9f7b02f377f1f70 (diff) | |
download | perl-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.xs | 13 |
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))); } |