mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-26 16:40:29 +01:00
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
This commit is contained in:
parent
67d882479b
commit
071017965f
4 changed files with 68 additions and 58 deletions
|
|
@ -1,3 +1,11 @@
|
||||||
|
2017-03-08 Barton E. Schaefer <schaefer@brasslantern.com>
|
||||||
|
|
||||||
|
* 40763: Src/Zle/compmatch.c, Src/Zle/computil.c, Src/utils.c:
|
||||||
|
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
|
||||||
|
|
||||||
2017-03-08 Daniel Shahaf <d.s@daniel.shahaf.name>
|
2017-03-08 Daniel Shahaf <d.s@daniel.shahaf.name>
|
||||||
|
|
||||||
* 40745 + 40753: Src/init.c, Src/params.c: Fix 'unset
|
* 40745 + 40753: Src/init.c, Src/params.c: Fix 'unset
|
||||||
|
|
|
||||||
|
|
@ -1548,27 +1548,11 @@ pattern_match(Cpattern p, char *s, Cpattern wp, char *ws)
|
||||||
{
|
{
|
||||||
convchar_t c, wc;
|
convchar_t c, wc;
|
||||||
convchar_t ind, wind;
|
convchar_t ind, wind;
|
||||||
int len = 0, wlen, mt, wmt;
|
int len = 0, wlen = 0, mt, wmt;
|
||||||
#ifdef MULTIBYTE_SUPPORT
|
|
||||||
mbstate_t lstate, wstate;
|
|
||||||
|
|
||||||
memset(&lstate, 0, sizeof(lstate));
|
|
||||||
memset(&wstate, 0, sizeof(wstate));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (p && wp && *s && *ws) {
|
while (p && wp && *s && *ws) {
|
||||||
/* First test the word character */
|
/* First test the word character */
|
||||||
#ifdef MULTIBYTE_SUPPORT
|
wc = unmeta_one(ws, &wlen);
|
||||||
wlen = mb_metacharlenconv_r(ws, &wc, &wstate);
|
|
||||||
#else
|
|
||||||
if (*ws == Meta) {
|
|
||||||
wc = STOUC(ws[1]) ^ 32;
|
|
||||||
wlen = 2;
|
|
||||||
} else {
|
|
||||||
wc = STOUC(*ws);
|
|
||||||
wlen = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
wind = pattern_match1(wp, wc, &wmt);
|
wind = pattern_match1(wp, wc, &wmt);
|
||||||
if (!wind)
|
if (!wind)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1576,18 +1560,7 @@ pattern_match(Cpattern p, char *s, Cpattern wp, char *ws)
|
||||||
/*
|
/*
|
||||||
* Now the line character.
|
* Now the line character.
|
||||||
*/
|
*/
|
||||||
#ifdef MULTIBYTE_SUPPORT
|
c = unmeta_one(s, &len);
|
||||||
len = mb_metacharlenconv_r(s, &c, &lstate);
|
|
||||||
#else
|
|
||||||
/* We have the character itself. */
|
|
||||||
if (*s == Meta) {
|
|
||||||
c = STOUC(s[1]) ^ 32;
|
|
||||||
len = 2;
|
|
||||||
} else {
|
|
||||||
c = STOUC(*s);
|
|
||||||
len = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* If either is "?", they match each other; no further tests.
|
* If either is "?", they match each other; no further tests.
|
||||||
* Apply this even if the character wasn't convertable;
|
* Apply this even if the character wasn't convertable;
|
||||||
|
|
@ -1627,17 +1600,7 @@ pattern_match(Cpattern p, char *s, Cpattern wp, char *ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (p && *s) {
|
while (p && *s) {
|
||||||
#ifdef MULTIBYTE_SUPPORT
|
c = unmeta_one(s, &len);
|
||||||
len = mb_metacharlenconv_r(s, &c, &lstate);
|
|
||||||
#else
|
|
||||||
if (*s == Meta) {
|
|
||||||
c = STOUC(s[1]) ^ 32;
|
|
||||||
len = 2;
|
|
||||||
} else {
|
|
||||||
c = STOUC(*s);
|
|
||||||
len = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!pattern_match1(p, c, &mt))
|
if (!pattern_match1(p, c, &mt))
|
||||||
return 0;
|
return 0;
|
||||||
p = p->next;
|
p = p->next;
|
||||||
|
|
@ -1645,17 +1608,7 @@ pattern_match(Cpattern p, char *s, Cpattern wp, char *ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (wp && *ws) {
|
while (wp && *ws) {
|
||||||
#ifdef MULTIBYTE_SUPPORT
|
wc = unmeta_one(ws, &wlen);
|
||||||
wlen = mb_metacharlenconv_r(ws, &wc, &wstate);
|
|
||||||
#else
|
|
||||||
if (*ws == Meta) {
|
|
||||||
wc = STOUC(ws[1]) ^ 32;
|
|
||||||
wlen = 2;
|
|
||||||
} else {
|
|
||||||
wc = STOUC(*ws);
|
|
||||||
wlen = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!pattern_match1(wp, wc, &wmt))
|
if (!pattern_match1(wp, wc, &wmt))
|
||||||
return 0;
|
return 0;
|
||||||
wp = wp->next;
|
wp = wp->next;
|
||||||
|
|
|
||||||
|
|
@ -4465,17 +4465,24 @@ cfp_matcher_pats(char *matcher, char *add)
|
||||||
if (m && m != pcm_err) {
|
if (m && m != pcm_err) {
|
||||||
char *tmp;
|
char *tmp;
|
||||||
int al = strlen(add), zl = ztrlen(add), tl, cl;
|
int al = strlen(add), zl = ztrlen(add), tl, cl;
|
||||||
VARARR(Cmatcher, ms, zl);
|
VARARR(Cmatcher, ms, zl); /* One Cmatcher per character */
|
||||||
Cmatcher *mp;
|
Cmatcher *mp;
|
||||||
Cpattern stopp;
|
Cpattern stopp;
|
||||||
int stopl = 0;
|
int stopl = 0;
|
||||||
|
|
||||||
|
/* zl >= (number of wide characters) is guaranteed */
|
||||||
memset(ms, 0, zl * sizeof(Cmatcher));
|
memset(ms, 0, zl * sizeof(Cmatcher));
|
||||||
|
|
||||||
for (; m && *add; m = m->next) {
|
for (; m && *add; m = m->next) {
|
||||||
stopp = NULL;
|
stopp = NULL;
|
||||||
if (!(m->flags & (CMF_LEFT|CMF_RIGHT))) {
|
if (!(m->flags & (CMF_LEFT|CMF_RIGHT))) {
|
||||||
if (m->llen == 1 && m->wlen == 1) {
|
if (m->llen == 1 && m->wlen == 1) {
|
||||||
|
/*
|
||||||
|
* In this loop and similar loops below we step
|
||||||
|
* through tmp one (possibly wide) character at a
|
||||||
|
* time. pattern_match() compares only the first
|
||||||
|
* character using unmeta_one() so keep in step.
|
||||||
|
*/
|
||||||
for (tmp = add, tl = al, mp = ms; tl; ) {
|
for (tmp = add, tl = al, mp = ms; tl; ) {
|
||||||
if (pattern_match(m->line, tmp, NULL, NULL)) {
|
if (pattern_match(m->line, tmp, NULL, NULL)) {
|
||||||
if (*mp) {
|
if (*mp) {
|
||||||
|
|
@ -4485,10 +4492,10 @@ cfp_matcher_pats(char *matcher, char *add)
|
||||||
} else
|
} else
|
||||||
*mp = m;
|
*mp = m;
|
||||||
}
|
}
|
||||||
cl = (*tmp == Meta) ? 2 : 1;
|
(void) unmeta_one(tmp, &cl);
|
||||||
tl -= cl;
|
tl -= cl;
|
||||||
tmp += cl;
|
tmp += cl;
|
||||||
mp += cl;
|
mp++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stopp = m->line;
|
stopp = m->line;
|
||||||
|
|
@ -4505,10 +4512,10 @@ cfp_matcher_pats(char *matcher, char *add)
|
||||||
} else
|
} else
|
||||||
*mp = m;
|
*mp = m;
|
||||||
}
|
}
|
||||||
cl = (*tmp == Meta) ? 2 : 1;
|
(void) unmeta_one(tmp, &cl);
|
||||||
tl -= cl;
|
tl -= cl;
|
||||||
tmp += cl;
|
tmp += cl;
|
||||||
mp += cl;
|
mp++;
|
||||||
}
|
}
|
||||||
} else if (m->llen) {
|
} else if (m->llen) {
|
||||||
stopp = m->line;
|
stopp = m->line;
|
||||||
|
|
@ -4531,7 +4538,7 @@ cfp_matcher_pats(char *matcher, char *add)
|
||||||
al = tmp - add;
|
al = tmp - add;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cl = (*tmp == Meta) ? 2 : 1;
|
(void) unmeta_one(tmp, &cl);
|
||||||
tl -= cl;
|
tl -= cl;
|
||||||
tmp += cl;
|
tmp += cl;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
Src/utils.c
42
Src/utils.c
|
|
@ -4787,6 +4787,48 @@ unmeta(const char *file_name)
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
* Unmetafy and compare two strings, comparing unsigned character values.
|
||||||
* "a\0" sorts after "a".
|
* "a\0" sorts after "a".
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue