diff --git a/ChangeLog b/ChangeLog index be8ba294fb..b13a74ca2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-02-11 Andreas Krebbel + + * sysdeps/s390/s390-64/utf8-utf16-z9.c: Disable hardware + instructions cu21 and cu24. Add well-formedness checking + parameter and adjust the software implementation. + * sysdeps/s390/s390-64/utf16-utf32-z9.c: Likewise. + 2010-02-10 Ulrich Drepper [BZ #11271] diff --git a/sysdeps/s390/s390-64/utf16-utf32-z9.c b/sysdeps/s390/s390-64/utf16-utf32-z9.c index 868dea68ca..14daf2118f 100644 --- a/sysdeps/s390/s390-64/utf16-utf32-z9.c +++ b/sysdeps/s390/s390-64/utf16-utf32-z9.c @@ -203,7 +203,10 @@ gconv_end (struct __gconv_step *data) swapping). */ #define BODY \ { \ - if (GLRO (dl_hwcap) & HWCAP_S390_ETF3EH) \ + /* The hardware instruction currently fails to report an error for \ + isolated low surrogates so we have to disable the instruction \ + until this gets resolved. */ \ + if (0) /* (GLRO (dl_hwcap) & HWCAP_S390_ETF3EH) */ \ { \ HARDWARE_CONVERT ("cu24 %0, %1, 1"); \ if (inptr != inend) \ @@ -229,6 +232,12 @@ gconv_end (struct __gconv_step *data) } \ else \ { \ + /* An isolated low-surrogate was found. This has to be \ + considered ill-formed. */ \ + if (__builtin_expect (u1 >= 0xdc00, 0)) \ + { \ + STANDARD_FROM_LOOP_ERR_HANDLER (2); \ + } \ /* It's a surrogate character. At least the first word says \ it is. */ \ if (__builtin_expect (inptr + 4 > inend, 0)) \ diff --git a/sysdeps/s390/s390-64/utf8-utf16-z9.c b/sysdeps/s390/s390-64/utf8-utf16-z9.c index 531d3ebd4b..5f73f3c59e 100644 --- a/sysdeps/s390/s390-64/utf8-utf16-z9.c +++ b/sysdeps/s390/s390-64/utf8-utf16-z9.c @@ -345,9 +345,12 @@ gconv_end (struct __gconv_step *data) Operation. */ #define BODY \ { \ - if (GLRO (dl_hwcap) & HWCAP_S390_ETF3EH) \ + /* The hardware instruction currently fails to report an error for \ + isolated low surrogates so we have to disable the instruction \ + until this gets resolved. */ \ + if (0) /* (GLRO (dl_hwcap) & HWCAP_S390_ETF3EH) */ \ { \ - HARDWARE_CONVERT ("cu21 %0, %1"); \ + HARDWARE_CONVERT ("cu21 %0, %1, 1"); \ if (inptr != inend) \ { \ /* Check if the third byte is \ @@ -388,7 +391,7 @@ gconv_end (struct __gconv_step *data) \ outptr += 2; \ } \ - else if (c >= 0x0800 && c <= 0xd7ff) \ + else if ((c >= 0x0800 && c <= 0xd7ff) || c > 0xdfff) \ { \ /* Three byte UTF-8 char. */ \ \