Module: wine Branch: master Commit: 448e68ab5b937d168f5d091d8f65a7de534a9891 URL: https://gitlab.winehq.org/wine/wine/-/commit/448e68ab5b937d168f5d091d8f65a7d...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Jan 9 11:50:20 2023 +0100
kernelbase: Fix FindNLSStringEx for strings with no primary weights.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53583 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53837
---
dlls/kernel32/tests/locale.c | 10 +++++++ dlls/kernelbase/locale.c | 66 +++++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 31 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 40706c15755..886240cc22c 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -6741,6 +6741,16 @@ static void test_FindNLSStringEx(void) { localeW, FIND_ENDSWITH, L"SimpleSimple", L"Simp", -1, 0xdeadbeef}, { localeW, FIND_FROMSTART, comb_s_accent1W, comb_s_accent2W, 0, 6 }, { localeW, FIND_FROMSTART, comb_q_accent1W, comb_q_accent2W, 2, 7 }, + { localeW, FIND_STARTSWITH, L"--Option", L"--", 0, 2}, + { localeW, FIND_ENDSWITH, L"Option--", L"--", 6, 2}, + { localeW, FIND_FROMSTART, L"----", L"--", 0, 2}, + { localeW, FIND_FROMEND, L"----", L"--", 2, 2}, + { localeW, FIND_FROMSTART, L"opt1--opt2--opt3", L"--", 4, 2}, + { localeW, FIND_FROMEND, L"opt1--opt2--opt3", L"--", 10, 2}, + { localeW, FIND_FROMSTART, L"x-oss-security", L"x-oss-", 0, 6}, + { localeW, FIND_FROMSTART, L"x-oss-security", L"-oss", 1, 4}, + { localeW, FIND_FROMSTART, L"x-oss-security", L"-oss--", -1, 0xdeadbeef}, + { localeW, FIND_FROMEND, L"x-oss-oss2", L"-oss", 5, 4}, }; unsigned int i;
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 5cc4152e491..1e96e49622e 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -3892,7 +3892,7 @@ static int find_substring( const struct sortguid *sortid, DWORD flags, const WCH struct sortkey_state val; BYTE primary[32]; BYTE primary_val[256]; - int i, start, found = -1, foundlen, pos = 0; + int i, start, len, found = -1, foundlen = 0, pos = 0; BOOL have_extra, have_extra_val; BYTE case_mask = 0x3f; UINT except = sortid->except; @@ -3915,43 +3915,47 @@ static int find_substring( const struct sortguid *sortid, DWORD flags, const WCH
for (start = 0; start < srclen; start++) { - pos = start; - while (pos < srclen && s.primary_pos < val.key_primary.len) + for (len = start + 1; len <= srclen; len++) { - while (pos < srclen && !s.key_primary.len) - pos += append_weights( sortid, flags, src, srclen, pos, - case_mask, except, compr_tables, &s, TRUE ); - - if (s.primary_pos + s.key_primary.len > val.key_primary.len) goto next; - if (memcmp( primary, val.key_primary.buf + s.primary_pos, s.key_primary.len )) goto next; - s.primary_pos += s.key_primary.len; - s.key_primary.len = 0; - } - if (s.primary_pos < val.key_primary.len) goto next; + pos = start; + while (pos < len && s.primary_pos <= val.key_primary.len) + { + while (pos < len && !s.key_primary.len) + pos += append_weights( sortid, flags, src, srclen, pos, + case_mask, except, compr_tables, &s, TRUE ); + + if (s.primary_pos + s.key_primary.len > val.key_primary.len) goto next; + if (memcmp( primary, val.key_primary.buf + s.primary_pos, s.key_primary.len )) goto next; + s.primary_pos += s.key_primary.len; + s.key_primary.len = 0; + } + if (s.primary_pos < val.key_primary.len) goto next;
- have_extra = remove_unneeded_weights( sortid, &s ); - if (compare_sortkeys( &s.key_diacritic, &val.key_diacritic, FALSE )) goto next; - if (compare_sortkeys( &s.key_case, &val.key_case, FALSE )) goto next; + have_extra = remove_unneeded_weights( sortid, &s ); + if (compare_sortkeys( &s.key_diacritic, &val.key_diacritic, FALSE )) goto next; + if (compare_sortkeys( &s.key_case, &val.key_case, FALSE )) goto next;
- if (have_extra && have_extra_val) - { - for (i = 0; i < 4; i++) - if (compare_sortkeys( &s.key_extra[i], &val.key_extra[i], i != 1 )) goto next; - } - else if (have_extra || have_extra_val) goto next; + if (have_extra && have_extra_val) + { + for (i = 0; i < 4; i++) + if (compare_sortkeys( &s.key_extra[i], &val.key_extra[i], i != 1 )) goto next; + } + else if (have_extra || have_extra_val) goto next;
- if (compare_sortkeys( &s.key_special, &val.key_special, FALSE )) goto next; + if (compare_sortkeys( &s.key_special, &val.key_special, FALSE )) goto next;
- found = start; - foundlen = pos - start; - if (flags & FIND_FROMSTART) break; + found = start; + foundlen = pos - start; + len = srclen; /* no need to continue checking longer strings */
- next: + next: + /* reset state */ + s.key_primary.len = s.key_diacritic.len = s.key_case.len = s.key_special.len = 0; + s.key_extra[0].len = s.key_extra[1].len = s.key_extra[2].len = s.key_extra[3].len = 0; + s.primary_pos = 0; + } if (flags & FIND_STARTSWITH) break; - /* reset state */ - s.key_primary.len = s.key_diacritic.len = s.key_case.len = s.key_special.len = 0; - s.key_extra[0].len = s.key_extra[1].len = s.key_extra[2].len = s.key_extra[3].len = 0; - s.primary_pos = 0; + if (flags & FIND_FROMSTART && found != -1) break; }
if (found != -1)