Tcl Source Code

View Ticket
Login
Ticket UUID: 3606139
Title: missing error check allows regexp to crash Tcl
Type: Bug Version: obsolete: 8.4.19
Submitter: tgl Created on: 2013-02-26 23:47:28
Subsystem: 43. Regexp Assigned To: nijtmans
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2013-02-27 21:54:59
Resolution: Fixed Closed By: nijtmans
    Closed on: 2013-02-27 08:24:37
Description:
The attached test case crashes the latest tclsh I have handy (8.5.11)

This is derived from a test case that was sent to the Postgres security list.  The Postgres project is currently thinking of treating this as just a regular bug and not a security issue, because as far as we can tell the potential damage is limited to a null-pointer dereference.  But we thought we'd let you know about it first to see if you feel it needs to be treated as a security issue.  If so, we'll need to organize coordinated releases.

Here's the analysis I sent to the Postgres security list:

I looked into this, and find that the core of the problem is that
parseqatom() is not defending itself against a NULL result from
parsebranch().  See this bit of code:

    if (!(SEE('|') || SEE(stopper) || SEE(EOS)))
        t->right = parsebranch(v, stopper, type, s2, rp, 1);
    else
    {
        EMPTYARC(s2, rp);
        t->right = subre(v, '=', 0, s2, rp);
    }
    assert(SEE('|') || SEE(stopper) || SEE(EOS));
    t->flags |= COMBINE(t->flags, t->right->flags);

If parsebranch (or subre for that matter) returns NULL, the
t->right->flags reference will obviously crash.

It turns out that parsebranch usually returns a valid struct subre
pointer even after an error, but it has two "NOERRN()" macros
(essentially "if (error occurred) return NULL") in places where only
an out-of-memory or regex-too-complex error would trigger the error
response.  This example case is provoking the regex-too-complex error.

This bug is aboriginal in Spencer's code.  The reason we've not seen it
reported before appears to be (a) typical errors such as regex syntax
errors don't end up returning NULL from parsebranch, and (2) you don't
get to the vulnerable code in parseqatom unless the regex has been found
to contain "messy stuff" (capturing parens, back reference, or
short/long preference clash).

The attached patch fixes it.  The added error check in parseqatom() is
the necessary fix, the additional check in parsebranch() is just
intended to not let processing continue after we know there's an error.

I'm not sure whether we should treat this as a security problem or just
fix it and be done.  AFAICS there is no risk of anything worse than a
null pointer dereference (no possibility of privilege escalation or
information leakage).  We've been less than consistent in the past as to
how to deal with simple crash cases like this; some have been treated as
security issues, but many more have just been handled as ordinary bugs.


BTW, credit for finding this issue goes to Tomasz Karlik <[email protected]>
User Comments: tgl added on 2013-02-27 21:54:59:
> Is Tom Lane (tgl) aware of the other recent regexp fix in Tcl?
> Tcl Bug 3604074.

I'll take a look, thanks for the pointer.

nijtmans added on 2013-02-27 20:32:42:
I tried to use [string repeat] but that leads to memory errors in stead of the expected error message.
Anyway, wrapping it over multiple lines works. I'm open to ideas for further improvmement.

dgp added on 2013-02-27 19:18:44:
Can't we craft that test case using [string repeat], etc.
instead of such an ugly literal?  Is that addition to the
contents the cause of fossil now thinking regexp.test
is a binary file?

dgp added on 2013-02-27 19:09:06:
Is Tom Lane (tgl) aware of the other recent regexp fix in Tcl?
Tcl Bug 3604074.

nijtmans added on 2013-02-27 15:24:37:
Agreed with the analysis. I see no reason to consider this a security bug as well.

Fixed now on core-8-4-branch, core-8-5-branch and trunk.

Many thanks!

tgl added on 2013-02-27 06:48:20:

File Added - 461005: regex-crash-fix.patch

tgl added on 2013-02-27 06:47:34:

File Added - 461004: tcl_crash.tcl

Attachments: