Skip to content

Resolve issue #20161: Evals that die under the debugger may or may not leak eval data#20182

Merged
demerphq merged 6 commits into
bleadfrom
yves/fix_20161
Sep 5, 2022
Merged

Resolve issue #20161: Evals that die under the debugger may or may not leak eval data#20182
demerphq merged 6 commits into
bleadfrom
yves/fix_20161

Conversation

@demerphq

@demerphq demerphq commented Aug 29, 2022

Copy link
Copy Markdown
Collaborator

We were leaking debug data, and not testing if we did. Assuming #20181 is applied, then we can apply this and fix #20161 which will enable use to merge #20168 if we want. This is rebased on top of #20181. Once that is applied only the most recent patch in this sequence will be relevant to this PR.

This patch changes the code to use try_yyparse() when compiling evals, while preserving the existing behavior for require.

@bram-perl

Copy link
Copy Markdown

I don't know if this is a good idea..
Reading https://perldoc.perl.org/perlinterp#Exception-handing (as was linked by @iabyn) I got the impression that CATCH_GET was done the way it is for optimizations..

Now the code will always use try_yyparse() (for eval) which I'm guessing is going to add some overhead..
What I don't know is how much that overhead is..

What I'm also wondering about: is this the only way to fix it? Skimming the code it appears that before commit f9bddea it first called SAVEDELETE and then called doeval while the current code first does doeval (which can die) and only then calls SAVEDELETE.. Would switching the order (i.e. calling SAVEDELETE before doeval) fix it too?

@demerphq

demerphq commented Aug 29, 2022

Copy link
Copy Markdown
Collaborator Author

@bram-perl I dont think you are right TBH. But I guess @iabyn will have to speak up. He was the one who suggested the CATCH_GET was superfluous after all, and removing it does fix the leaking debug data. I dont think it changes the performance signature at all, that concern relates to execution not compilation.

Note that the added overhead is that of adding a call to JMPENV_PUSH()/JMPENV_POP which boils down to some bookkeeping and a call to Perl_procsetjmp(). In the grand scheme of doing an eval that is a tiny thing. Also because this is compilation we push an env and then pop it, they wont cascade except with regard to BEGIN, and that is already a problem that is being tackled in a different PR.

Also it doesnt make sense to me, @iabyn added try_yyparse, which is now no longer used. It makes a lot more sense to me that it should be used than it should be there totally unused.

@demerphq demerphq requested a review from iabyn August 29, 2022 19:10
@bram-perl

Copy link
Copy Markdown

Also it doesnt make sense to me, @iabyn added try_yyparse, which is now no longer used. It makes a lot more sense to me that it should be used than it should be there totally unused.

Just for reference: reason for that is commit d7e3f70.

Details

That commit added an earlier 'catchable runloop' which resulted in S_doeval_compile to always be called with a false value for CATCH_GET.

I suspect (but did not verify) that an alternative fix could've been to add a 'catchable runloop' further down in S_doeval_compile namely in the block:

    if (PL_unitcheckav) {
        OP *es = PL_eval_start;
        call_list(PL_scopestack_ix, PL_unitcheckav);
        PL_eval_start = es;
    }

@demerphq

demerphq commented Aug 29, 2022 via email

Copy link
Copy Markdown
Collaborator Author

@bram-perl

Copy link
Copy Markdown

For UNITCHECK see #20161 (comment)

The test only works correct by accident (imo).

@demerphq

demerphq commented Aug 30, 2022 via email

Copy link
Copy Markdown
Collaborator Author

@khwilliamson

Copy link
Copy Markdown
Contributor

A more general comment. It was suggested on some of my commit messages that it should dereference the issue's name so that the reader doesn't have to each time it is read. That effectively could be to copy/paste.

@demerphq demerphq changed the title Resolve issue #20161 Resolve issue #20161: Evals that die under the debugger may or may not leak eval data Aug 30, 2022
@demerphq demerphq force-pushed the yves/fix_20161 branch 3 times, most recently from ed5460e to 757dc7a Compare September 3, 2022 13:53
We can just do the count before and after.
CATCH_GET is never true in this code, so we never called try_yyparse()
which in turn meant we leaked debug data from failed evals. With this
in place an eval that dies during compile will always be handled by
doeval_comp() properly.

This includes changes to t/comp/readlines.t so it tests code that
croaks during compile, which used to leak and fail test but was not
actually tested.

This fixes GH Issue #20161.
We test BEGIN{die}, but not UNITCHECK{die}. Lets do both.
Comment thread pp_ctl.c Outdated
Make sure we actually return via pp_evalcomp() when UNITCHECK
inside of an eval dies.

Thanks to Bram for the work figuring this out.
Also add SAFE_FUNCTION__ which ensures that the value
is "UNKNOWN" on platforms that dont support __func__.
@demerphq demerphq merged commit f31da5f into blead Sep 5, 2022
@demerphq demerphq deleted the yves/fix_20161 branch September 5, 2022 05:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Evals that die under the debugger may or may not leak eval data depending on how they die.

3 participants