Re: [PHP-DEV] [RFC] [VOTE] PREG_THROW_ON_ERROR

[email protected] (Robert Humphries)
Newsgroups php.internals
Message-ID <CADjdLZ+aT8yq9BGMva0n+4mxf+Gj9g3sqzO=2WYU0-s7SxfC5w@mail.gmail.com>
> I think there might be a misunderstanding based on how you phrased that
> paragraph. To provide a more specific example:

Sorry - I think I might have just worded my message poorly, as your
more detailed example is how I understood the `RandomException` to
look like. I think the core is that in both cases; but specifically
with the session example, the action is what has failed (and
regardless of cause then it is desired to have a single catch to
handle that).

> preg_replace_callback() is different in that I explicitly pass in a
> callback and thus I'm technically in full control over the code that is
> being executed and I can theoretically know what exceptions could
> possibly be thrown and might intentionally want to handle them
> explicitly

Looking at this from a different angle - the first part (in that the
developer is in full control of the code) might be the most important
part here. If the developer wants any failure (a non-zero
`preg_last_error()` result or an error that occurs during the
callback) to have a single catch block then the developer is able to
throw a `PregException` themselves (or a child of `PregException`).

However if `PregException` wraps any `Throwable`s in the userland
callbacks, a developer who wants to have multiple catch blocks (or
throw some exceptions that propagate to a higher scope in their
callback) can only do that by catching and rethrowing.

On Mon, Sep 7, 2026 at 1:31 PM Tim Düsterhus <[email protected]> wrote:
>
> Hi
>
> On 2026-09-07 13:58, Robert Humphries wrote:
> >> Arguably this specific case is a bit debatable, but as the author of
> >> the
> >> throwable policy RFC, I believe that it is at least violated in
> >> spirit.
> >> The goal of the throwable policy generally, and also with regard to
> >> that
> >> specific paragraph is to allow reliably handling groups of errors
> >> without needing to wrap every individual statement into its own
> >> try-catch block.
> >
> > Obviously you wrote the policy and so are best placed to interpret it
> > (and I am not a core developer / person with voting rights); however I
> > agree with the angle Osama is coming from here - I wouldn't say this
> > is an error that is (always) part of the same group. There wasn't any
> > error in the call to `preg_replace_callback` itself (or any of its
> > functionality) - the error was in a way during the processing of the
>
> Yes, I agree that this case is not entirely clear-cut - and it's good
> we're having this discussion now.
>
> > If I have understood the other example correctly, this contradicts
> > quite significantly with the CSPRNG throwing an Exception that
> > `RandomException` contains - as the failure is a core issue within the
> > function call itself as opposed to logic that occurs in userland.
>
> I think there might be a misunderstanding based on how you phrased that
> paragraph. To provide a more specific example:
>
> Consider I have a session implementation that uses Redis as its session
> storage backend. Session IDs need to be created using secure randomness,
> i.e. using the CSPRNG. Both the Redis backend and the CSPRNG can
> theoretically fail. As a user when create a new session I want to be
> able to just catch (SessionInitializedFailedException) and not care
> about whether the CSPRNG or the Redis connection failed, and I might not
> even know if it's Redis, Memcache, a File System or a MySQL database.
> Thus any underlying issues must be wrapped into a session-specific
> exception.
>
> preg_replace_callback() is different in that I explicitly pass in a
> callback and thus I'm technically in full control over the code that is
> being executed and I can theoretically know what exceptions could
> possibly be thrown and might intentionally want to handle them
> explicitly. On the other hand, failing to execute the callback means
> that the replacing operation failed, no further callbacks will be called
> and preg_replace_callback() will not return anything - and that is a
> “running this regex failed” a.k.a. PregException situation to me.
>
> > If anything, I would argue that under the policy this should go the
> > other way and become `PregError`:
> >> The Error hierarchy MUST NOT be used for errors that are expected to
> >> be thrown (and caught) during normal operation of a PHP program.
> > In terms of the possible errors that could occur, I would expect at
> > least `PREG_INTERNAL_ERROR`, `PREG_BAD_UTF8_ERROR` &
> > `PREG_JIT_STACKLIMIT_ERROR` to be code errors that require a developer
> > to need to correct their code (as my understanding of these would be
> > that the pattern is invalid, or not quoted correctly, etc. Although
> > `PREG_BACKTRACK_LIMIT_ERROR` & `PREG_RECURSION_LIMIT_ERROR` are more
> > likely to occur based on user input, then the limit for both is
> > controlled by an ini setting - so again, this likely isn't something I
> > would say is expected to be thrown and caught during normal operation
> > of a PHP program. The final error (`PREG_BAD_UTF8_OFFSET_ERROR`) I
> > _think_ would still likely need a code change to fix it occurring -
> > although I have only done a quick Google to see _when_ it may occur.
>
> This is a good point. I agree that things like pattern compilation
> failures should be a PregError, since this is a clear programmer error
> and regular expressions are not supposed to be untrusted inputs. For the
> error error situations I would need to check as well if they are
> expected during regular operation or not. The backtrack or recursion
> limits I can see being caught intentionally to provide better error
> messages to a user (thus PregException).
>
> Best regards
> Tim Düsterhus
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.