summaryrefslogtreecommitdiff
path: root/locale.c
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2016-07-26 14:09:46 -0600
committerKarl Williamson <khw@cpan.org>2016-08-02 19:31:07 -0600
commit1adab0a73adeec06e0378323cb104a410fd4cc1b (patch)
treef536f8f0c8fd494e90173615ae725d708429cfec /locale.c
parentd4ff958684aa549b9e8db9c80ac5dc2b08461e38 (diff)
downloadperl-1adab0a73adeec06e0378323cb104a410fd4cc1b.tar.gz
locale.c: Some systems include NUL in strxfrm() return
strxfrm() is supposed to not include the trailing NUL in the length returned, but we have run into a Windows system that does include it (some Windows ones don't), so test for and compensate for this possibility.
Diffstat (limited to 'locale.c')
-rw-r--r--locale.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/locale.c b/locale.c
index 8c7a5d6c01..2101782b95 100644
--- a/locale.c
+++ b/locale.c
@@ -1758,6 +1758,7 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
/* Then the transformation of the input. We loop until successful, or we
* give up */
for (;;) {
+
*xlen = strxfrm(xbuf + COLLXFRM_HDR_LEN, s, xAlloc - COLLXFRM_HDR_LEN);
/* If the transformed string occupies less space than we told strxfrm()
@@ -1765,6 +1766,15 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
* string. */
if (*xlen < xAlloc - COLLXFRM_HDR_LEN) {
+ /* Some systems include a trailing NUL in the returned length.
+ * Ignore it, using a loop in case multiple trailing NULs are
+ * returned. */
+ while ( (*xlen) > 0
+ && *(xbuf + COLLXFRM_HDR_LEN + (*xlen) - 1) == '\0')
+ {
+ (*xlen)--;
+ }
+
/* If the first try didn't get it, it means our prediction was low.
* Modify the coefficients so that we predict a larger value in any
* future transformations */
@@ -1827,9 +1837,9 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
goto bad;
/* A well-behaved strxfrm() returns exactly how much space it needs
- * (not including the trailing NUL) when it fails due to not enough
- * space being provided. Assume that this is the case unless it's been
- * proven otherwise */
+ * (usually not including the trailing NUL) when it fails due to not
+ * enough space being provided. Assume that this is the case unless
+ * it's been proven otherwise */
if (LIKELY(PL_strxfrm_is_behaved) && first_time) {
xAlloc = *xlen + COLLXFRM_HDR_LEN + 1;
}