Re: [regression?] trailing slash required in .gitattributes
From: Duy Nguyen <hidden>
Date: 2016-06-15 22:56:29
Subsystem:
the rest · Maintainer:
Linus Torvalds
On Fri, Mar 22, 2013 at 06:24:39PM -0400, Jeff King wrote:
I'm having trouble figuring out the right solution for this.
Thanks for looking into this. It was on my todo list, but you beat me to it :)
But then here we'll end up feeding "foo/" to be compared with "foo",
which we don't want. For a pattern "foo", we want to match _either_
"foo/" or "foo". So you'd think something like:
if (pathlen && pathname[pathlen-1] == '/')
pathlen--;
would work. But it seems that match_basename, despite taking the length
of all of the strings we pass it, will happily use NUL-terminated
functions like strcmp or fnmatch. Converting the former to check lengths
should be pretty straightforward. But there is no version of fnmatch
that does what we want. I wonder if we using wildmatch can get around
this limitation.You can use nwildmatch() from this patch. I tested it lightly with t3070-wildmatch.sh, feeding the strings with no terminating NUL. It seems to work ok. -- 8< -- Subject: [PATCH] wildmatch: do not require "text" to be NUL-terminated This may be helpful when we just want to match a part of "text". nwildmatch can be used for this purpose. Signed-off-by: Nguyễn Thái Ngọc Duy <redacted> --- wildmatch.c | 25 +++++++++++++------------ wildmatch.h | 11 +++++++++-- 2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/wildmatch.c b/wildmatch.c
index 7192bdc..f97ae2a 100644
--- a/wildmatch.c
+++ b/wildmatch.c@@ -52,7 +52,8 @@ typedef unsigned char uchar; #define ISXDIGIT(c) (ISASCII(c) && isxdigit(c)) /* Match pattern "p" against "text" */ -static int dowild(const uchar *p, const uchar *text, unsigned int flags) +static int dowild(const uchar *p, const uchar *text, + const uchar *textend, unsigned int flags) { uchar p_ch; const uchar *pattern = p;
@@ -60,8 +61,9 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) for ( ; (p_ch = *p) != '\0'; text++, p++) { int matched, match_slash, negated; uchar t_ch, prev_ch; - if ((t_ch = *text) == '\0' && p_ch != '*') + if (text >= textend && p_ch != '*') return WM_ABORT_ALL; + t_ch = *text; if ((flags & WM_CASEFOLD) && ISUPPER(t_ch)) t_ch = tolower(t_ch); if ((flags & WM_CASEFOLD) && ISUPPER(p_ch))
@@ -101,7 +103,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) * both foo/bar and foo/a/bar. */ if (p[0] == '/' && - dowild(p + 1, text, flags) == WM_MATCH) + dowild(p + 1, text, textend, flags) == WM_MATCH) return WM_MATCH; match_slash = 1; } else
@@ -130,9 +132,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) /* the slash is consumed by the top-level for loop */ break; } - while (1) { - if (t_ch == '\0') - break; + while (text < textend) { /* * Try to advance faster when an asterisk is * followed by a literal. We know in this case
@@ -145,18 +145,18 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) p_ch = *p; if ((flags & WM_CASEFOLD) && ISUPPER(p_ch)) p_ch = tolower(p_ch); - while ((t_ch = *text) != '\0' && + while (text < textend && (match_slash || t_ch != '/')) { if ((flags & WM_CASEFOLD) && ISUPPER(t_ch)) t_ch = tolower(t_ch); if (t_ch == p_ch) break; - text++; + t_ch = *++text; } if (t_ch != p_ch) return WM_NOMATCH; } - if ((matched = dowild(p, text, flags)) != WM_NOMATCH) { + if ((matched = dowild(p, text, textend, flags)) != WM_NOMATCH) { if (!match_slash || matched != WM_ABORT_TO_STARSTAR) return matched; } else if (!match_slash && t_ch == '/')
@@ -261,12 +261,13 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) } } - return *text ? WM_NOMATCH : WM_MATCH; + return text < textend ? WM_NOMATCH : WM_MATCH; } /* Match the "pattern" against the "text" string. */ -int wildmatch(const char *pattern, const char *text, +int nwildmatch(const char *pattern, const char *text, int textlen, unsigned int flags, struct wildopts *wo) { - return dowild((const uchar*)pattern, (const uchar*)text, flags); + return dowild((const uchar*)pattern, (const uchar*)text, + (const uchar*)text + textlen, flags); }
diff --git a/wildmatch.h b/wildmatch.h
index 4090c8f..cdd7544 100644
--- a/wildmatch.h
+++ b/wildmatch.h@@ -12,7 +12,14 @@ struct wildopts; -int wildmatch(const char *pattern, const char *text, - unsigned int flags, +int nwildmatch(const char *pattern, const char *text, + int len, unsigned int flags, struct wildopts *wo); + +/* Match the "pattern" against the "text" string. */ +static inline int wildmatch(const char *pattern, const char *text, + unsigned int flags, struct wildopts *wo) +{ + return nwildmatch(pattern, text, strlen(text), flags, wo); +} #endif
--
1.8.2.83.gc99314b
-- 8< --