mirror of
https://github.com/postgres/postgres.git
synced 2026-05-28 04:35:45 -04:00
Fix overflows with ts_headline()
The options "StartSel", "StopSel" and "FragmentDelimiter" given by a caller of the SQL function ts_headline() have their lengths stored as int16. When providing values larger than PG_INT16_MAX, it was possible to overflow the length values stored, leading to incorrect behaviors in generateHeadline(), in most cases translating to a crash. Attempting to use values for these options larger than PG_INT16_MAX is now blocked. Some test cases are added to cover our tracks. Reported-by: Xint Code Author: Michael Paquier <michael@paquier.xyz> Backpatch-through: 14 Security: CVE-2026-6473
This commit is contained in:
parent
6b6b26fdec
commit
5919e0005b
3 changed files with 39 additions and 3 deletions
|
|
@ -2627,6 +2627,9 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||
int max_fragments = 0;
|
||||
bool highlightall = false;
|
||||
ListCell *l;
|
||||
size_t startsellen;
|
||||
size_t stopsellen;
|
||||
size_t fragdelimlen;
|
||||
|
||||
/* Extract configuration option values */
|
||||
prs->startsel = NULL;
|
||||
|
|
@ -2716,9 +2719,24 @@ prsd_headline(PG_FUNCTION_ARGS)
|
|||
prs->fragdelim = pstrdup(" ... ");
|
||||
|
||||
/* Caller will need these lengths, too */
|
||||
prs->startsellen = strlen(prs->startsel);
|
||||
prs->stopsellen = strlen(prs->stopsel);
|
||||
prs->fragdelimlen = strlen(prs->fragdelim);
|
||||
startsellen = strlen(prs->startsel);
|
||||
stopsellen = strlen(prs->stopsel);
|
||||
fragdelimlen = strlen(prs->fragdelim);
|
||||
if (startsellen > PG_INT16_MAX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("value for \"%s\" is too long", "StartSel")));
|
||||
if (stopsellen > PG_INT16_MAX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("value for \"%s\" is too long", "StopSel")));
|
||||
if (fragdelimlen > PG_INT16_MAX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("value for \"%s\" is too long", "FragmentDelimiter")));
|
||||
prs->startsellen = startsellen;
|
||||
prs->stopsellen = stopsellen;
|
||||
prs->fragdelimlen = fragdelimlen;
|
||||
|
||||
PG_RETURN_POINTER(prs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2144,6 +2144,16 @@ NOTICE: text-search query doesn't contain lexemes: ""
|
|||
foo bar
|
||||
(1 row)
|
||||
|
||||
-- Test for large values of StartSel, StopSel and FragmentDelimiter
|
||||
SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'),
|
||||
'StartSel=' || repeat('x', 32768));
|
||||
ERROR: value for "StartSel" is too long
|
||||
SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'),
|
||||
'StopSel=' || repeat('x', 32768));
|
||||
ERROR: value for "StopSel" is too long
|
||||
SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'),
|
||||
'FragmentDelimiter=' || repeat('x', 32768));
|
||||
ERROR: value for "FragmentDelimiter" is too long
|
||||
--Rewrite sub system
|
||||
CREATE TABLE test_tsquery (txtkeyword TEXT, txtsample TEXT);
|
||||
\set ECHO none
|
||||
|
|
|
|||
|
|
@ -646,6 +646,14 @@ SELECT ts_headline('english',
|
|||
SELECT ts_headline('english',
|
||||
'foo bar', to_tsquery('english', ''));
|
||||
|
||||
-- Test for large values of StartSel, StopSel and FragmentDelimiter
|
||||
SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'),
|
||||
'StartSel=' || repeat('x', 32768));
|
||||
SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'),
|
||||
'StopSel=' || repeat('x', 32768));
|
||||
SELECT ts_headline('english', 'foo barbar', to_tsquery('english', 'foo'),
|
||||
'FragmentDelimiter=' || repeat('x', 32768));
|
||||
|
||||
--Rewrite sub system
|
||||
|
||||
CREATE TABLE test_tsquery (txtkeyword TEXT, txtsample TEXT);
|
||||
|
|
|
|||
Loading…
Reference in a new issue