regcomp.c: Fix some alignment problems
authorKarl Williamson <public@khwilliamson.com>
Wed, 12 Feb 2014 03:27:30 +0000 (20:27 -0700)
committerKarl Williamson <public@khwilliamson.com>
Mon, 17 Feb 2014 18:26:41 +0000 (11:26 -0700)
commit7dcac5f6a5195002b55c935ee1d67f67e1df280b
treed60f6153eafb425e1accc696cc641460caec6156
parent55f616c39553c61edd12406823d815451f74c97f
regcomp.c: Fix some alignment problems

The bracketed character class (e.g. /[abc]/) in regular expression
patterns is implemented as an ANYOF regnode.  There are several
different structs used for these, each a superset of the next smaller
size, with extra fields tacked on to its end.  Bits in the part common
to all of them are set to indicate which size this particular instance
is.

Several functions in regcomp.c take the largest of these as a formal
parameter, even though a smaller one may actually be passed.  This
avoids the need to have casts to access the optional fields, but the
code needs to be careful to check the common part bits before trying to
access a portion that may not actually be present.  This practice dates
to at least Perl v5.6.2.

It turns out that there is further a problem with this if the tacked-on
fields require a stricter alignment than the common fields.  The code in
the functions may assume that the actual parameter has suitable
alignment, which may not be the case.

Some months ago I added some extra optional pointer fields, which have
stricter alignment requirements on 64-bit machines than the common
portion, but no apparent problems ensued.

Then, I changed things slightly, so that the gcc compiler on HP machines
found an optimization possibility whose use required the proper
alignment, which wasn't present, and bus errors started happening there.

Tony Cook diagnosed the problem.  A summary of his work can be found
at http://markmail.org/message/hee5zyah7rb62c72

This commit changes the formal parameter to the smallest ANYOF struct,
and uses casts to acess the optional portions.

I don't know how common the coding style formerly used in regcomp.c is,
but it is dangerous and can lead to unrelated changes causing errors.

This commit should enable gcc builds to complete on the HP gcc smokers
(previously miniperl built, but crashed in building the rest of perl),
but we're not sure because unrelated header issues on the gcc on the
machine that we have access to prevent blead from fully compiling there.

There remain alignment bugs which will cause the tests to fail there, as
the appended pointer field needs to have strict alignment on that
platform, but when the regnodes are allocated alignment isn't done.  I
am working on fixing those.
embed.fnc
perl.h
proto.h
regcomp.c