Check for interrupts and stack overflow in TParserGet().

TParserGet() recurses for some token types, meaning it's possible
to drive it to stack overflow.  Since this is a minority behavior,
I chose to add the check_stack_depth() call to the two places that
recurse rather than doing it during every single call.

While at it, add CHECK_FOR_INTERRUPTS(), because this can run
unpleasantly long for long inputs.

Per bug #17995 from Zuming Jiang.  This is old, so back-patch
to all supported branches.

Discussion: https://postgr.es/m/17995-9f20ff3e6389db4c@postgresql.org
This commit is contained in:
Tom Lane 2023-06-24 17:18:08 -04:00
parent 96f96398d3
commit c7f33a197b
1 changed files with 15 additions and 0 deletions

View File

@ -18,6 +18,7 @@
#include "catalog/pg_collation.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "tsearch/ts_locale.h"
#include "tsearch/ts_public.h"
#include "tsearch/ts_type.h"
@ -639,6 +640,12 @@ p_ishost(TParser *prs)
tmpprs->wanthost = true;
/*
* Check stack depth before recursing. (Since TParserGet() doesn't
* normally recurse, we put the cost of checking here not there.)
*/
check_stack_depth();
if (TParserGet(tmpprs) && tmpprs->type == HOST)
{
prs->state->posbyte += tmpprs->lenbytetoken;
@ -662,6 +669,12 @@ p_isURLPath(TParser *prs)
tmpprs->state = newTParserPosition(tmpprs->state);
tmpprs->state->state = TPS_InURLPathFirst;
/*
* Check stack depth before recursing. (Since TParserGet() doesn't
* normally recurse, we put the cost of checking here not there.)
*/
check_stack_depth();
if (TParserGet(tmpprs) && tmpprs->type == URLPATH)
{
prs->state->posbyte += tmpprs->lenbytetoken;
@ -1705,6 +1718,8 @@ TParserGet(TParser *prs)
{
const TParserStateActionItem *item = NULL;
CHECK_FOR_INTERRUPTS();
Assert(prs->state);
if (prs->state->posbyte >= prs->lenstr)