regexec.c: Fix failure to match problem
authorKarl Williamson <khw@cpan.org>
Tue, 1 Mar 2016 20:07:45 +0000 (13:07 -0700)
committerKarl Williamson <khw@cpan.org>
Tue, 1 Mar 2016 20:41:21 +0000 (13:41 -0700)
commit451c6e0b1522c6ac8f890794e0432c7f5e8d1013
tree380e63a9598d37adbf701d27838c8847bd7316d6
parent22026221701648ac03c6b1a17b13cd2f49cf38f4
regexec.c: Fix failure to match problem

This bug has shown up only under EBCDIC so far, but could affect other
code.

Commit dcf88e3433dcd5bc25811f9769e82d04c61a1d5a fixed a bug in which a
macro parameter needed to be dereferenced.  Until then, the failure to
dereference meant some code that turned out to be faulty, was
effectively always skipped.  So that commit, while correct in and of
itself, exposed a pre-existing bug.

It was hard for me to believe at first that a change of simply adding a
missing '*' could have broken things this way.  But the clue was that
the only characters that were affected were the set of C1 controls, and
only when the target matched string was in UTF-8, and only on EBCDIC
systems.  The difference between EBCDIC and ASCII platforms in this
regard is that the C1 controls under UTF-8 are represented by a single
byte on EBCDIC systems, and two bytes on ASCII.  The test that adding
the dereference to is looking for characters that are single bytes under
both UTF-8 and not, and hence would give different results on EBCDIC and
ASCII platforms for exactly the set of C1 controls.

The code in question looks up an input code point to see if it is
matched by an ANYOF node, the kind generated for bracketed character
classes.  The first N code points are stored in a bit vector.  (N is
generally 256, but perl can be compiled to make that larger.)  If there
are no complications, the answer can be found directly by just looking
up the code point in the vector.  But if there are complications, a
function is called to sort them all out.  The macro looks for
complications, and calls the function if needed, but does the lookup
directly if not.  One of those complications is that the input needs to
be decoded to its actual code point value if the target is UTF-8 and the
code point isn't a single byte then.  After the dereference fix, the
caller of the macro knew correctly that this was a single byte, and so
was calling the macro,  But it turns out that the macro, as commented,
was expecting to be called only if the target was not-UTF-8, and so
unconditionally said to the function that it wasn't UTF-8, and so the
function didn't work properly.

The solution is to simply call the function in the macros with the
correct value of whether the target string is UTF-8 or not.
regexec.c