pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Tomas Vondra <tomas.vondra@2ndquadrant.com>
To: pgsql-hackers@postgresql.org
Cc: Teodor Sigaev <teodor@sigaev.ru>
Subject: Re: CREATE TEXT SEARCH DICTIONARY segfaulting on 9.6+
Date: Sun, 13 Oct 2019 23:38:08 +0200
Message-ID: <20191013213808.wfhtvkqcvlvbdkmz@development> (raw)
In-Reply-To: <20191013012610.2p2fp3zzpoav7jzf@development>
References: <20191013012610.2p2fp3zzpoav7jzf@development>

I spent a bit of time investigating this, and it seems the new code is
somewhat too trusting when it comes to data from the affix/dict files.
In this particular case, it boils down to this code in NISortDictionary:

    if (Conf->useFlagAliases)
    {
        for (i = 0; i < Conf->nspell; i++)
        {
            char   *end;

            if (*Conf->Spell[i]->p.flag != '\0')
            {
                curaffix = strtol(Conf->Spell[i]->p.flag, &end, 10);
                if (Conf->Spell[i]->p.flag == end || errno == ERANGE)
                    ereport(ERROR,
                            (errcode(ERRCODE_CONFIG_FILE_ERROR),
                             errmsg("invalid affix alias \"%s\"",
                                    Conf->Spell[i]->p.flag)));
            }
            ...
            Conf->Spell[i]->p.d.affix = curaffix;
            ...
        }
        ...
    }

So it simply grabs whatever it finds in the dict file, parses it and
then (later) we use it as index to access the AffixData array, even if
the value is way out of bounds.

For example in the example, hunspell_sample_long.affix contains about
10 affixes, but then we parse the hunspell_sample_num.dict file, and we
stumble upon

    book/302,301,202,303

and we parse the flags as integers, and interpret them as indexes in the
AffixData array. Clearly, 303 is waaaay out of bounds, triggering the
segfault crash.

So I think we need some sort of cross-check here. We certainly need to
make NISortDictionary() check the affix value is within AffixData
bounds, and error out when the index is non-sensical (maybe negative
and/or exceeding nAffixData). Maybe there's a simple way to check if the
affix/dict files match. The failing affix has

    FLAG num

while with

    FLAG long

it works just fine. But I'm not sure that's actually possible, because I
don't see anything in hunspell_sample_num.dict that would allow us to
decide that it expects "FLAG num" and not "FLAG long". Furthermore, we
certainly can't rely on this - we still need to check the range.


regards

-- 
Tomas Vondra                  http://www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services 





view thread (5+ messages)  latest in thread

Message-ID: <20191013213808.wfhtvkqcvlvbdkmz@development>
Permalink:  ../20191013213808.wfhtvkqcvlvbdkmz@development/
Also on:    postgresql.org/message-id/20191013213808.wfhtvkqcvlvbdkmz@development

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: tomas.vondra@2ndquadrant.com, teodor@sigaev.ru
  Subject: Re: CREATE TEXT SEARCH DICTIONARY segfaulting on 9.6+
  In-Reply-To: <20191013213808.wfhtvkqcvlvbdkmz@development>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox