This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix regex failures on big-endian systems
authorKarl Williamson <khw@cpan.org>
Fri, 26 Feb 2016 20:57:10 +0000 (13:57 -0700)
committerKarl Williamson <khw@cpan.org>
Fri, 26 Feb 2016 21:27:51 +0000 (14:27 -0700)
Commit accb4364d92e26c20e6a538fc04d1af52a8b94e2 caused regexes to fail
on big-endian systems.  It was because I used SvCUR where I should have
been using SvLEN, and was overwriting the final byte of real data with
0, which didn't matter as long as that byte was 0, which in our smokes
on litlle-endian systems, it was.

Further clarification is that inversion lists are stored as UV*, whereas
the scalar handling code is expecting char*.  By casting, it all works
out, except that the final byte is kept as a single char NUL.  I was
trying to write that final byte as a byte, but by using SvCUR, I was
getting a byte in one of the UVs.  With small numbers on a little-endian
system, that byte will be 0 anyway, but not on a big-endian one.

regcomp.c

index 7c2f419..206a515 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -8357,7 +8357,7 @@ S_invlist_replace_list(pTHX_ SV * dest, SV * src)
 
     const UV src_len          = _invlist_len(src);
     const bool src_offset     = *get_invlist_offset_addr(src);
-    const STRLEN src_byte_len = SvCUR(src);
+    const STRLEN src_byte_len = SvLEN(src);
     char * array              = SvPVX(src);
 
     const int oldtainted = TAINT_get;
@@ -8367,6 +8367,7 @@ S_invlist_replace_list(pTHX_ SV * dest, SV * src)
     assert(SvTYPE(src) == SVt_INVLIST);
     assert(SvTYPE(dest) == SVt_INVLIST);
     assert(! invlist_is_iterating(src));
+    assert(SvCUR(src) < SvLEN(src));
 
     /* Make sure it ends in the right place with a NUL, as our inversion list
      * manipulations aren't careful to keep this true, but sv_usepvn_flags()