From c8e8151746c31cffabceb6c8a47afa98f041f327 Mon Sep 17 00:00:00 2001 From: John Marino Date: Wed, 1 Mar 2017 16:21:30 +0300 Subject: [PATCH] 6904 collation: Fix expansion substitutions Reviewed by: Robert Mustacchi Reviewed by: Yuri Pankov Approved by: Dan McDonald --- usr/src/lib/libc/port/locale/collate.c | 30 +++++----- usr/src/lib/libc/port/locale/wcscoll.c | 102 ++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 57 deletions(-) diff --git a/usr/src/lib/libc/port/locale/collate.c b/usr/src/lib/libc/port/locale/collate.c index 4dead90973..a8d7bf60d5 100644 --- a/usr/src/lib/libc/port/locale/collate.c +++ b/usr/src/lib/libc/port/locale/collate.c @@ -209,27 +209,18 @@ substsearch(const struct lc_collate *lcc, const wchar_t key, int pass) return (p->pri); } -/* - * Note: for performance reasons, we have expanded bsearch here. This avoids - * function call overhead with each comparison. - */ - static collate_chain_t * chainsearch(const struct lc_collate *lcc, const wchar_t *key, int *len) { - int low; - int high; + int low = 0; + int high = lcc->lc_info->chain_count - 1; int next, compar, l; collate_chain_t *p; - collate_chain_t *tab; + collate_chain_t *tab = lcc->lc_chain_table; - if (lcc->lc_info->chain_count == 0) + if (high < 0) return (NULL); - low = 0; - high = lcc->lc_info->chain_count - 1; - tab = lcc->lc_chain_table; - while (low <= high) { next = (low + high) / 2; p = tab + next; @@ -259,7 +250,7 @@ largesearch(const struct lc_collate *lcc, const wchar_t key) collate_large_t *p; collate_large_t *tab = lcc->lc_large_table; - if (lcc->lc_info->large_count == 0) + if (high < 0) return (NULL); while (low <= high) { @@ -303,7 +294,10 @@ _collate_lookup(const struct lc_collate *lcc, const wchar_t *t, if ((sptr = *state) != NULL) { *pri = *sptr; sptr++; - *state = *sptr ? sptr : NULL; + if ((sptr == *state) || (sptr == NULL)) + *state = NULL; + else + *state = sptr; *len = 0; return; } @@ -364,7 +358,7 @@ _collate_lookup(const struct lc_collate *lcc, const wchar_t *t, * code ensures this for us. */ if ((sptr = substsearch(lcc, *pri, which)) != NULL) { - if ((*pri = *sptr) != 0) { + if ((*pri = *sptr) > 0) { sptr++; *state = *sptr ? sptr : NULL; } @@ -443,6 +437,7 @@ _collate_wxfrm(const struct lc_collate *lcc, const wchar_t *src, wchar_t *xf, errno = EINVAL; goto fail; } + state = NULL; pri = COLLATE_MAX_PRIORITY; } if (room) { @@ -462,6 +457,7 @@ _collate_wxfrm(const struct lc_collate *lcc, const wchar_t *src, wchar_t *xf, errno = EINVAL; goto fail; } + state = NULL; continue; } if (room) { @@ -596,6 +592,7 @@ _collate_sxfrm(const wchar_t *src, char *xf, size_t room, locale_t loc) errno = EINVAL; goto fail; } + state = NULL; pri = COLLATE_MAX_PRIORITY; } @@ -622,6 +619,7 @@ _collate_sxfrm(const wchar_t *src, char *xf, size_t room, locale_t loc) errno = EINVAL; goto fail; } + state = NULL; continue; } diff --git a/usr/src/lib/libc/port/locale/wcscoll.c b/usr/src/lib/libc/port/locale/wcscoll.c index 4bf32ff010..26b39c9da2 100644 --- a/usr/src/lib/libc/port/locale/wcscoll.c +++ b/usr/src/lib/libc/port/locale/wcscoll.c @@ -70,6 +70,7 @@ wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc) const int32_t *st2 = NULL; const wchar_t *w1 = ws1; const wchar_t *w2 = ws2; + int check1, check2; /* special pass for UNDEFINED */ if (pass == lcc->lc_directive_count) { @@ -103,25 +104,38 @@ wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc) } if (direc & DIRECTIVE_POSITION) { - while ((*w1 || st1) && (*w2 || st2)) { + while (*w1 && *w2) { pri1 = pri2 = 0; - _collate_lookup(lcc, w1, &len1, &pri1, pass, - &st1); - if (pri1 <= 0) { - if (pri1 < 0) { - errno = EINVAL; - goto fail; + check1 = check2 = 1; + while ((pri1 == pri2) && (check1 || check2)) { + if (check1) { + _collate_lookup(lcc, w1, &len1, + &pri1, pass, &st1); + if (pri1 < 0) { + errno = EINVAL; + goto fail; + } + if (!pri1) { + /*CSTYLED*/ + pri1 = COLLATE_MAX_PRIORITY; + st1 = NULL; + } + check1 = (st1 != NULL); } - pri1 = COLLATE_MAX_PRIORITY; - } - _collate_lookup(lcc, w2, &len2, &pri2, pass, - &st2); - if (pri2 <= 0) { - if (pri2 < 0) { - errno = EINVAL; - goto fail; + if (check2) { + _collate_lookup(lcc, w2, &len2, + &pri2, pass, &st2); + if (pri2 < 0) { + errno = EINVAL; + goto fail; + } + if (!pri2) { + /*CSTYLED*/ + pri2 = COLLATE_MAX_PRIORITY; + st2 = NULL; + } + check2 = (st2 != NULL); } - pri2 = COLLATE_MAX_PRIORITY; } if (pri1 != pri2) { ret = pri1 - pri2; @@ -131,29 +145,38 @@ wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc) w2 += len2; } } else { - while ((*w1 || st1) && (*w2 || st2)) { + while (*w1 && *w2) { pri1 = pri2 = 0; - while (*w1) { - _collate_lookup(lcc, w1, &len1, - &pri1, pass, &st1); - if (pri1 > 0) - break; - if (pri1 < 0) { - errno = EINVAL; - goto fail; + check1 = check2 = 1; + while ((pri1 == pri2) && (check1 || check2)) { + while (check1 && *w1) { + _collate_lookup(lcc, w1, &len1, + &pri1, pass, &st1); + if (pri1 > 0) + break; + if (pri1 < 0) { + errno = EINVAL; + goto fail; + } + st1 = NULL; + w1 += 1; } - w1 += len1; - } - while (*w2) { - _collate_lookup(lcc, w2, &len2, - &pri2, pass, &st2); - if (pri2 > 0) - break; - if (pri2 < 0) { - errno = EINVAL; - goto fail; + check1 = (st1 != NULL); + while (check2 && *w2) { + _collate_lookup(lcc, w2, &len2, + &pri2, pass, &st2); + if (pri2 > 0) + break; + if (pri2 < 0) { + errno = EINVAL; + goto fail; + } + st2 = NULL; + w2 += 1; } - w2 += len2; + check2 = (st2 != NULL); + if (!pri1 || !pri2) + break; } if (!pri1 || !pri2) break; @@ -178,10 +201,8 @@ wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc) ret = 0; end: - if (tr1) - free(tr1); - if (tr2) - free(tr2); + free(tr1); + free(tr2); return (ret); @@ -190,7 +211,6 @@ fail: goto end; } - int wcscoll(const wchar_t *ws1, const wchar_t *ws2) { -- 2.11.4.GIT