This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
PATCH: [perl #134329] Use after free in regcomp.c
authorKarl Williamson <khw@cpan.org>
Fri, 23 Aug 2019 18:40:24 +0000 (12:40 -0600)
committerKarl Williamson <khw@cpan.org>
Fri, 30 Aug 2019 14:22:05 +0000 (08:22 -0600)
commit3b2e5620ed4a6b341f97ffd1d4b6466cc2c4bc5b
tree8b30c65722b8e864f36f6d719fcdda0bc38efdbf
parentad68fe3be5b41877fd43630888e16a4f4fea3923
PATCH: [perl #134329] Use after free in regcomp.c

A compiled regex is composed of nodes, forming a linked list, with
normally a maximum of 16 bits used to specify the offset of the next
link.  For patterns that require more space than this, the nodes that
jump around are replaced with ones that have wider offsets.  Most nodes
are unaffected, as they just contain the offset of the next node, and
that number is always small.  The jump nodes are the ones affected.

When compiling a pattern, the 16 bit mechanism is used, until it
overflows, at which point the pattern is recompiled with the long jumps
instead.

When I rewrote the compiler last year to make it generally one pass, I
noticed a lot of the cases where a node was added didn't check if the
result overflowed (the function that does this returns FALSE in that
case).  I presumed the prior authors knew better, and did not change
things, except to put in a bogus value in the link (offset) field that
should cause a crash if it were used.  That's what's happening in this
ticket.

But seeing this example, it's clear that the return value should be
checked every time, because you can reach the limit at any time.  This
commit changes to do that, and to require the function's return value to
not be ignored, to guard against future changes.

My guess is that the reason it generally worked when there were multiple
passes is that the first pass didn't do anything except count space, and
that at some point before the end of the pass the return value did get
checked, so by the time the nodes were allocated for real, it knew
enough to use the long jumps.
MANIFEST
embed.fnc
proto.h
regcomp.c
t/re/bigfuzzy_not_utf8.t [new file with mode: 0644]