]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix memory-safety bugs in the ispell/hunspell dictionary loader.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 2 Aug 2026 17:22:39 +0000 (13:22 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 2 Aug 2026 17:22:39 +0000 (13:22 -0400)
Allocate CompoundAffix with room for its terminator, initialize the
old-format flag buffer before NIAddAffix(), and reject incomplete or
missing Hunspell AF aliases.  None of these errors would be likely to
trigger on real dictionary files, accounting for the lack of previous
reports; but they're certainly bugs.

Bug: #19595
Reported-by: Michael Malis <michaelmalis2@gmail.com>
Author: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19595-7dc18b4e212c4757@postgresql.org
Backpatch-through: 14

src/backend/tsearch/spell.c

index 3ded3cf7d5f88c3cea70e0940c2bba9a7c2024fd..06c90cc0b9faf1ba3dccd552f27ab0b59e28daa4 100644 (file)
@@ -1182,12 +1182,18 @@ getAffixFlagSet(IspellDict *Conf, char *s)
                                         errmsg("invalid affix alias \"%s\"", s)));
 
                if (curaffix > 0 && curaffix < Conf->nAffixData)
+               {
+                       if (Conf->AffixData[curaffix] == NULL)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_CONFIG_FILE_ERROR),
+                                                errmsg("invalid affix alias \"%s\"", s)));
 
                        /*
                         * Do not subtract 1 from curaffix because empty string was added
                         * in NIImportOOAffixes
                         */
                        return Conf->AffixData[curaffix];
+               }
                else if (curaffix > Conf->nAffixData)
                        ereport(ERROR,
                                        (errcode(ERRCODE_CONFIG_FILE_ERROR),
@@ -1422,6 +1428,13 @@ nextline:
        tsearch_readline_end(&trst);
        if (ptype)
                pfree(ptype);
+
+       /* Reject incomplete AF alias table. */
+       if (Conf->useFlagAliases && curaffix != naffix)
+               ereport(ERROR,
+                               (errcode(ERRCODE_CONFIG_FILE_ERROR),
+                                errmsg("number of aliases is less than specified number %d",
+                                               naffix - 1)));
 }
 
 /*
@@ -1449,6 +1462,8 @@ NIImportAffixes(IspellDict *Conf, const char *filename)
        bool            oldformat = false;
        char       *recoded = NULL;
 
+       flag[0] = '\0';                         /* no flag seen yet */
+
        if (!tsearch_readline_begin(&trst, filename))
                ereport(ERROR,
                                (errcode(ERRCODE_CONFIG_FILE_ERROR),
@@ -1997,7 +2012,8 @@ NISortAffixes(IspellDict *Conf)
        /* Store compound affixes in the Conf->CompoundAffix array */
        if (Conf->naffixes > 1)
                qsort(Conf->Affix, Conf->naffixes, sizeof(AFFIX), cmpaffix);
-       Conf->CompoundAffix = ptr = palloc_array(CMPDAffix, Conf->naffixes);
+       /* +1 for terminator */
+       Conf->CompoundAffix = ptr = palloc_array(CMPDAffix, Conf->naffixes + 1);
        ptr->affix = NULL;
 
        for (int i = 0; i < Conf->naffixes; i++)