diff options
author | Barton E. Schaefer <schaefer@zsh.org> | 2017-03-08 21:26:55 -0800 |
---|---|---|
committer | Barton E. Schaefer <schaefer@zsh.org> | 2017-03-08 21:26:55 -0800 |
commit | 071017965f469c88b10467205f30ea3e609e56dc (patch) | |
tree | a6472c26ba37ff83be987c782eef231d989d2607 /Src/utils.c | |
parent | 67d882479b61165c5d58bd72430d6009f4a7f25f (diff) | |
download | zsh-071017965f469c88b10467205f30ea3e609e56dc.tar.gz zsh-071017965f469c88b10467205f30ea3e609e56dc.tar.xz zsh-071017965f469c88b10467205f30ea3e609e56dc.zip |
40763: count wide characters and Cmatcher pointers more sanely in cfp_matcher_pats(), and count characters in pattern_match() the same way to stay in sync
Might not fix wide-char matching in completion matcher-lists but should avoid wild pointer crash
Diffstat (limited to 'Src/utils.c')
-rw-r--r-- | Src/utils.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/Src/utils.c b/Src/utils.c index 9669944f6..b3fa3d24c 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -4788,6 +4788,48 @@ unmeta(const char *file_name) } /* + * Unmetafy just one character and store the number of bytes it occupied. + */ +/**/ +mod_export convchar_t +unmeta_one(const char *in, int *sz) +{ + convchar_t wc; + int newsz; +#ifdef MULTIBYTE_SUPPORT + int ulen; + mbstate_t wstate; +#endif + + if (!sz) + sz = &newsz; + *sz = 0; + + if (!in || !*in) + return 0; + +#ifdef MULTIBYTE_SUPPORT + memset(&wstate, 0, sizeof(wstate)); + ulen = mb_metacharlenconv_r(in, &wc, &wstate); + while (ulen-- > 0) { + if (in[*sz] == Meta) + *sz += 2; + else + *sz += 1; + } +#else + if (in[0] == Meta) { + *sz = 2; + wc = STOUC(in[1] ^ 32); + } else { + *sz = 1; + wc = STOUC(in[0]); + } +#endif + return wc; +} + +/* * Unmetafy and compare two strings, comparing unsigned character values. * "a\0" sorts after "a". * |