Skip to content

fix: disallow using multiple throw expressions #18512

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

xepozz
Copy link

@xepozz xepozz commented May 6, 2025

Preventing throw throw throw ... hell

https://3v4l.org/nJ65d

@nielsdos
Copy link
Member

nielsdos commented May 6, 2025

This doesn't stop me from writing variations of this:

throw ((throw new Exception) ?? 1);

There are many such variations and you can't cover all of them with a simple AST check.

@xepozz
Copy link
Author

xepozz commented May 6, 2025

@nielsdos any thought how to prevent so?

@iluuu1994
Copy link
Member

But why do we need to prevent it at all? Compilers accept dumb programs, we can't possibly reject all of them (without also rejecting valid ones).

@nielsdos
Copy link
Member

nielsdos commented May 6, 2025

@nielsdos any thought how to prevent so?

I suppose you'd have to recursively check the AST subtree. But I agree with Ilija that trying to prevent this at compile time is likely not worth the hassle.

@TimWolla
Copy link
Member

TimWolla commented May 6, 2025

In any case it would also be a breaking change (legal PHP programs become illegal) and thus would require an RFC.

@xepozz
Copy link
Author

xepozz commented May 7, 2025

Should I close this then?

@iluuu1994
Copy link
Member

iluuu1994 commented May 7, 2025

@xepozz You are free to create an RFC if you like. Such a check would be possible to implement by traversing the AST, or recording the fact that we're inside a throw expression and checking this flag in zend_compile_throw(). But I would not be in favor, as it doesn't achieve much. E.g. you can still write if (throw new Exception()) {}, 42 + throw new Exception, and so forth, none of which make sense. Such checks really belong in a static analyzer like PHPStan.

If you're not interested in creating an RFC, then yes, please close the issue.

@xepozz
Copy link
Author

xepozz commented May 8, 2025

by traversing the AST

I've thought about it, but it will degrade performance, won't it?

Also checking a flag in zend_compile_throw isn't a good idea for such case:

throw my_exc();

function my_exc() { throw new \Exception(); }

@iluuu1994
Copy link
Member

I've thought about it, but it will degrade performance, won't it?

Performance in the compiler is not particularly crucial, plus you can avoid the slowdown almost completely by storing a boolean flag in CG(context) and then checking whether this is set in zend_compile_throw().

Also checking a flag in zend_compile_throw isn't a good idea for such case:

This is not a concern. The call is not followed at compile-time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants