From: Michael Haggerty <mhagger@xxxxxxxxxxxx> Add a function parse_refname_prefix() that can read a possible refname from the front of a string. This is like check_refname_format(), except: * It accepts (string, len) parameters and can therefore handle non-NUL-terminated strings. * It returns the length of the part of the string that was parsed, allowing it to be used for refnames that are followed by additional characters. Re-implement check_refname_format() using the new function. Rename function check_refname_component() to parse_refname_component() for consistency. Signed-off-by: Michael Haggerty <mhagger@xxxxxxxxxxxx> --- refs.c | 64 ++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 44 insertions(+), 20 deletions(-) diff --git a/refs.c b/refs.c index 3b41252..387da83 100644 --- a/refs.c +++ b/refs.c @@ -907,24 +907,30 @@ static inline int bad_ref_char(int ch) /* * Try to read one refname component from the front of ref. Return - * the length of the component found, or -1 if the component is not - * legal. + * the length of the component found, or -1 if the start of the string + * cannot be interpreted as a component of a legal refname. */ -static int check_refname_component(const char *ref, int flags) +static int parse_refname_component(const char *ref, int len, int flags) { - int i, len = strlen(ref); + int i; char last = '\0'; for (i = 0; i < len; i++) { char ch = ref[i]; - if (ch == '\0' || ch == '/') - break; + if (ch == '/') + break; /* Component terminated by "..". */ if (bad_ref_char(ch)) - return -1; /* Illegal character in refname. */ - if (last == '.' && ch == '.') - return -1; /* Refname contains "..". */ - if (last == '@' && ch == '{') - return -1; /* Refname contains "@{". */ + break; /* Component terminated by illegal character. */ + if (last == '.' && ch == '.') { + /* Component terminated by "..". */ + i--; + break; + } + if (last == '@' && ch == '{') { + /* Component terminated by "@{". */ + i--; + break; + } last = ch; } if (i == 0) @@ -944,17 +950,26 @@ static int check_refname_component(const char *ref, int flags) return i; } -int check_refname_format(const char *ref, int flags) +/* + * Try to interpret the beginning of a string as a refname. Return + * the length of the part of the string that could constitute a valid + * refname, or -1 if the start of the string cannot possibly be + * interpreted as a refname. flags has the same interpretation as for + * check_refname_format(). + */ +static int parse_refname_prefix(const char *ref, int len, int flags) { int component_len, component_count = 0; + const char *p = ref; + int valid_len; while (1) { - /* We are at the start of a path component. */ - component_len = check_refname_component(ref, flags); + /* p is at the start of a path component. */ + component_len = parse_refname_component(p, len, flags); if (component_len < 0) { if ((flags & REFNAME_REFSPEC_PATTERN) && - ref[0] == '*' && - (ref[1] == '\0' || ref[1] == '/')) { + len && p[0] == '*' && + (len == 1 || p[1] == '/')) { /* Accept one wildcard as a full refname component. */ flags &= ~REFNAME_REFSPEC_PATTERN; component_len = 1; @@ -963,17 +978,26 @@ int check_refname_format(const char *ref, int flags) } } component_count++; - if (ref[component_len] == '\0') + if (component_len == len || p[component_len] != '/') break; /* Skip to next component. */ - ref += component_len + 1; + p += component_len + 1; + len -= component_len + 1; } - if (ref[component_len - 1] == '.') + valid_len = p + component_len - ref; + + if (ref[valid_len - 1] == '.') return -1; /* Refname ends with '.'. */ if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2) return -1; /* Refname has only one component. */ - return 0; + return valid_len; +} + +int check_refname_format(const char *ref, int flags) +{ + int len = strlen(ref); + return parse_refname_prefix(ref, len, flags) == len ? 0 : -1; } const char *prettify_refname(const char *name) -- 1.7.7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html