aboutsummaryrefslogtreecommitdiff
path: root/attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'attr.c')
-rw-r--r--attr.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/attr.c b/attr.c
index 410bca613..60fe48f3b 100644
--- a/attr.c
+++ b/attr.c
@@ -36,6 +36,27 @@ static unsigned hash_name(const char *name, int namelen)
return val;
}
+static int invalid_attr_name(const char *name, int namelen)
+{
+ /*
+ * Attribute name cannot begin with '-' and from
+ * [-A-Za-z0-9_.]. We'd specifically exclude '=' for now,
+ * as we might later want to allow non-binary value for
+ * attributes, e.g. "*.svg merge=special-merge-program-for-svg"
+ */
+ if (*name == '-')
+ return -1;
+ while (namelen--) {
+ char ch = *name++;
+ if (! (ch == '-' || ch == '.' || ch == '_' ||
+ ('0' <= ch && ch <= '9') ||
+ ('a' <= ch && ch <= 'z') ||
+ ('A' <= ch && ch <= 'Z')) )
+ return -1;
+ }
+ return 0;
+}
+
struct git_attr *git_attr(const char *name, int len)
{
unsigned hval = hash_name(name, len);
@@ -48,6 +69,9 @@ struct git_attr *git_attr(const char *name, int len)
return a;
}
+ if (invalid_attr_name(name, len))
+ return NULL;
+
a = xmalloc(sizeof(*a) + len + 1);
memcpy(a->name, name, len);
a->name[len] = 0;
@@ -68,7 +92,7 @@ struct git_attr *git_attr(const char *name, int len)
* (1) glob pattern.
* (2) whitespace
* (3) whitespace separated list of attribute names, each of which
- * could be prefixed with '!' to mean "not set".
+ * could be prefixed with '-' to mean "not set".
*/
struct attr_state {
@@ -114,6 +138,12 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
name += strlen(ATTRIBUTE_MACRO_PREFIX);
name += strspn(name, blank);
namelen = strcspn(name, blank);
+ if (invalid_attr_name(name, namelen)) {
+ fprintf(stderr,
+ "%.*s is not a valid attribute name: %s:%d\n",
+ namelen, name, src, lineno);
+ return NULL;
+ }
}
else
is_macro = 0;
@@ -126,11 +156,21 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
while (*cp) {
const char *ep;
ep = cp + strcspn(cp, blank);
- if (pass) {
+ if (!pass) {
+ if (*cp == '-')
+ cp++;
+ if (invalid_attr_name(cp, ep - cp)) {
+ fprintf(stderr,
+ "%.*s is not a valid attribute name: %s:%d\n",
+ (int)(ep - cp), cp,
+ src, lineno);
+ return NULL;
+ }
+ } else {
struct attr_state *e;
e = &(res->state[num_attr]);
- if (*cp == '!') {
+ if (*cp == '-') {
e->unset = 1;
cp++;
}
@@ -146,8 +186,9 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
sizeof(*res) +
sizeof(struct attr_state) * num_attr +
(is_macro ? 0 : namelen + 1));
- if (is_macro)
+ if (is_macro) {
res->u.attr = git_attr(name, namelen);
+ }
else {
res->u.pattern = (char*)&(res->state[num_attr]);
memcpy(res->u.pattern, name, namelen);
@@ -194,7 +235,7 @@ static void free_attr_elem(struct attr_stack *e)
}
static const char *builtin_attr[] = {
- "[attr]binary !diff !crlf",
+ "[attr]binary -diff -crlf",
NULL,
};