From 1fc1b82b2fe1011565a157bc660eceab60ed7923 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 13 Aug 2026 11:20:27 -0400 Subject: [PATCH] Consistently enforce tsvector/tsquery maximum lengths. Some places rejected individual tokens longer than MAXSTRLEN, while others rejected ones longer than MAXSTRLEN-1. The data structure is perfectly capable of handling MAXSTRLEN, so there's nothing wrong with using the looser bound. Moreover, as things stand there is a dump/reload hazard: some code paths permit construction of a tsvector or tsquery that would later be rejected by tsvectorin or tsqueryin. So standardize on using MAXSTRLEN. Identical remarks apply to MAXSTRPOS (the total data length), so fix that too. Back-patch, in hopes of avoiding cases where a value acceptable to one supported release is not acceptable to another. Author: Tom Lane Reviewed-by: Zsolt Parragi Discussion: https://postgr.es/m/CAN4CZFNYQo4zfbRR435uD0vSfuy5y7dnFOXDfKr9zYoL1JnAxA@mail.gmail.com Backpatch-through: 14 --- src/backend/tsearch/ts_parse.c | 4 ++-- src/backend/utils/adt/tsquery.c | 6 +++--- src/backend/utils/adt/tsvector.c | 4 ++-- src/backend/utils/adt/tsvector_op.c | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/backend/tsearch/ts_parse.c b/src/backend/tsearch/ts_parse.c index bc5d5197e71..f82545ac1d4 100644 --- a/src/backend/tsearch/ts_parse.c +++ b/src/backend/tsearch/ts_parse.c @@ -379,7 +379,7 @@ parsetext(Oid cfgId, ParsedText *prs, char *buf, int buflen) PointerGetDatum(&lemm), PointerGetDatum(&lenlemm))); - if (type > 0 && lenlemm >= MAXSTRLEN) + if (type > 0 && lenlemm > MAXSTRLEN) { #ifdef IGNORE_LONGLEXEME ereport(NOTICE, @@ -582,7 +582,7 @@ hlparsetext(Oid cfgId, HeadlineParsedText *prs, TSQuery query, char *buf, int bu PointerGetDatum(&lemm), PointerGetDatum(&lenlemm))); - if (type > 0 && lenlemm >= MAXSTRLEN) + if (type > 0 && lenlemm > MAXSTRLEN) { #ifdef IGNORE_LONGLEXEME ereport(NOTICE, diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c index e692a0f9d11..fd3c7a3ba1e 100644 --- a/src/backend/utils/adt/tsquery.c +++ b/src/backend/utils/adt/tsquery.c @@ -548,12 +548,12 @@ pushValue_internal(TSQueryParserState state, pg_crc32 valcrc, int distance, int { QueryOperand *tmp; - if (distance >= MAXSTRPOS) + if (distance > MAXSTRPOS) ereturn(state->escontext,, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("value is too big in tsquery: \"%s\"", state->buffer))); - if (lenval >= MAXSTRLEN) + if (lenval > MAXSTRLEN) ereturn(state->escontext,, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("operand is too long in tsquery: \"%s\"", @@ -581,7 +581,7 @@ pushValue(TSQueryParserState state, char *strval, int lenval, int16 weight, bool { pg_crc32 valcrc; - if (lenval >= MAXSTRLEN) + if (lenval > MAXSTRLEN) ereturn(state->escontext,, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("word is too long in tsquery: \"%s\"", diff --git a/src/backend/utils/adt/tsvector.c b/src/backend/utils/adt/tsvector.c index d3981bafd37..154e7ee7e1b 100644 --- a/src/backend/utils/adt/tsvector.c +++ b/src/backend/utils/adt/tsvector.c @@ -208,12 +208,12 @@ tsvectorin(PG_FUNCTION_ARGS) while (gettoken_tsvector(state, &token, &toklen, &pos, &poslen, NULL)) { - if (toklen >= MAXSTRLEN) + if (toklen > MAXSTRLEN) ereturn(escontext, (Datum) 0, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("word is too long (%ld bytes, max %ld bytes)", (long) toklen, - (long) (MAXSTRLEN - 1)))); + (long) MAXSTRLEN))); if (cur - tmpbuf > MAXSTRPOS) ereturn(escontext, (Datum) 0, diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index b6f969e0532..200090aee0a 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -777,12 +777,12 @@ array_to_tsvector(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_ZERO_LENGTH_CHARACTER_STRING), errmsg("lexeme array may not contain empty strings"))); - if (toklen >= MAXSTRLEN) + if (toklen > MAXSTRLEN) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("word is too long (%d bytes, max %d bytes)", toklen, - MAXSTRLEN - 1))); + MAXSTRLEN))); } /* Sort and de-dup, because this is required for a valid tsvector. */