|
|
68e6c8 |
diff -ur b/attr.c c/attr.c
|
|
|
68e6c8 |
--- b/attr.c 2013-06-10 22:01:55.000000000 +0200
|
|
|
68e6c8 |
+++ c/attr.c 2023-02-21 12:25:20.735892607 +0100
|
|
|
68e6c8 |
@@ -12,6 +12,7 @@
|
|
|
68e6c8 |
#include "exec_cmd.h"
|
|
|
68e6c8 |
#include "attr.h"
|
|
|
68e6c8 |
#include "dir.h"
|
|
|
68e6c8 |
+#include "utf8.h"
|
|
|
68e6c8 |
|
|
|
68e6c8 |
const char git_attr__true[] = "(builtin)true";
|
|
|
68e6c8 |
const char git_attr__false[] = "\0(builtin)false";
|
|
|
68e6c8 |
@@ -55,26 +56,36 @@
|
|
|
68e6c8 |
return val;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
|
|
|
68e6c8 |
-static int invalid_attr_name(const char *name, int namelen)
|
|
|
68e6c8 |
+static int attr_name_valid(const char *name, size_t namelen)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
/*
|
|
|
68e6c8 |
* Attribute name cannot begin with '-' and must consist of
|
|
|
68e6c8 |
* characters from [-A-Za-z0-9_.].
|
|
|
68e6c8 |
*/
|
|
|
68e6c8 |
if (namelen <= 0 || *name == '-')
|
|
|
68e6c8 |
- return -1;
|
|
|
68e6c8 |
+ return 0;
|
|
|
68e6c8 |
while (namelen--) {
|
|
|
68e6c8 |
char ch = *name++;
|
|
|
68e6c8 |
if (! (ch == '-' || ch == '.' || ch == '_' ||
|
|
|
68e6c8 |
('0' <= ch && ch <= '9') ||
|
|
|
68e6c8 |
('a' <= ch && ch <= 'z') ||
|
|
|
68e6c8 |
('A' <= ch && ch <= 'Z')) )
|
|
|
68e6c8 |
- return -1;
|
|
|
68e6c8 |
+ return 0;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
- return 0;
|
|
|
68e6c8 |
+ return 1;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
|
|
|
68e6c8 |
-static struct git_attr *git_attr_internal(const char *name, int len)
|
|
|
68e6c8 |
+static void report_invalid_attr(const char *name, size_t len,
|
|
|
68e6c8 |
+ const char *src, int lineno)
|
|
|
68e6c8 |
+{
|
|
|
68e6c8 |
+ struct strbuf err = STRBUF_INIT;
|
|
|
68e6c8 |
+ strbuf_addf(&err, _("%.*s is not a valid attribute name"),
|
|
|
68e6c8 |
+ (int) len, name);
|
|
|
68e6c8 |
+ fprintf(stderr, "%s: %s:%d\n", err.buf, src, lineno);
|
|
|
68e6c8 |
+ strbuf_release(&err;;
|
|
|
68e6c8 |
+}
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+static struct git_attr *git_attr_internal(const char *name, size_t len)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
unsigned hval = hash_name(name, len);
|
|
|
68e6c8 |
unsigned pos = hval % HASHSIZE;
|
|
|
68e6c8 |
@@ -86,7 +97,7 @@
|
|
|
68e6c8 |
return a;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
|
|
|
68e6c8 |
- if (invalid_attr_name(name, len))
|
|
|
68e6c8 |
+ if (!attr_name_valid(name, len))
|
|
|
68e6c8 |
return NULL;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
a = xmalloc(sizeof(*a) + len + 1);
|
|
|
68e6c8 |
@@ -142,7 +153,7 @@
|
|
|
68e6c8 |
struct git_attr *attr;
|
|
|
68e6c8 |
} u;
|
|
|
68e6c8 |
char is_macro;
|
|
|
68e6c8 |
- unsigned num_attr;
|
|
|
68e6c8 |
+ size_t num_attr;
|
|
|
68e6c8 |
struct attr_state state[FLEX_ARRAY];
|
|
|
68e6c8 |
};
|
|
|
68e6c8 |
|
|
|
68e6c8 |
@@ -159,7 +170,7 @@
|
|
|
68e6c8 |
struct attr_state *e)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
const char *ep, *equals;
|
|
|
68e6c8 |
- int len;
|
|
|
68e6c8 |
+ size_t len;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
ep = cp + strcspn(cp, blank);
|
|
|
68e6c8 |
equals = strchr(cp, '=');
|
|
|
68e6c8 |
@@ -174,10 +185,8 @@
|
|
|
68e6c8 |
cp++;
|
|
|
68e6c8 |
len--;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
- if (invalid_attr_name(cp, len)) {
|
|
|
68e6c8 |
- fprintf(stderr,
|
|
|
68e6c8 |
- "%.*s is not a valid attribute name: %s:%d\n",
|
|
|
68e6c8 |
- len, cp, src, lineno);
|
|
|
68e6c8 |
+ if (!attr_name_valid(cp, len)) {
|
|
|
68e6c8 |
+ report_invalid_attr(cp, len, src, lineno);
|
|
|
68e6c8 |
return NULL;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
} else {
|
|
|
68e6c8 |
@@ -199,8 +208,7 @@
|
|
|
68e6c8 |
static struct match_attr *parse_attr_line(const char *line, const char *src,
|
|
|
68e6c8 |
int lineno, int macro_ok)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
- int namelen;
|
|
|
68e6c8 |
- int num_attr, i;
|
|
|
68e6c8 |
+ size_t namelen, num_attr, i;
|
|
|
68e6c8 |
const char *cp, *name, *states;
|
|
|
68e6c8 |
struct match_attr *res = NULL;
|
|
|
68e6c8 |
int is_macro;
|
|
|
68e6c8 |
@@ -209,6 +217,12 @@
|
|
|
68e6c8 |
if (!*cp || *cp == '#')
|
|
|
68e6c8 |
return NULL;
|
|
|
68e6c8 |
name = cp;
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+ if (strlen(line) >= ATTR_MAX_LINE_LENGTH) {
|
|
|
68e6c8 |
+ warning(_("ignoring overly long attributes line %d"), lineno);
|
|
|
68e6c8 |
+ return NULL;
|
|
|
68e6c8 |
+ }
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
namelen = strcspn(name, blank);
|
|
|
68e6c8 |
if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&
|
|
|
68e6c8 |
!prefixcmp(name, ATTRIBUTE_MACRO_PREFIX)) {
|
|
|
68e6c8 |
@@ -221,10 +235,8 @@
|
|
|
68e6c8 |
name += strlen(ATTRIBUTE_MACRO_PREFIX);
|
|
|
68e6c8 |
name += strspn(name, blank);
|
|
|
68e6c8 |
namelen = strcspn(name, blank);
|
|
|
68e6c8 |
- if (invalid_attr_name(name, namelen)) {
|
|
|
68e6c8 |
- fprintf(stderr,
|
|
|
68e6c8 |
- "%.*s is not a valid attribute name: %s:%d\n",
|
|
|
68e6c8 |
- namelen, name, src, lineno);
|
|
|
68e6c8 |
+ if (!attr_name_valid(name, namelen)) {
|
|
|
68e6c8 |
+ report_invalid_attr(cp, namelen, src, lineno);
|
|
|
68e6c8 |
return NULL;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
@@ -241,10 +253,9 @@
|
|
|
68e6c8 |
return NULL;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
|
|
|
68e6c8 |
- res = xcalloc(1,
|
|
|
68e6c8 |
- sizeof(*res) +
|
|
|
68e6c8 |
- sizeof(struct attr_state) * num_attr +
|
|
|
68e6c8 |
- (is_macro ? 0 : namelen + 1));
|
|
|
68e6c8 |
+ res = xcalloc(1, st_add3(sizeof(*res),
|
|
|
68e6c8 |
+ st_mult(sizeof(struct attr_state), num_attr),
|
|
|
68e6c8 |
+ is_macro ? 0 : namelen + 1));
|
|
|
68e6c8 |
if (is_macro)
|
|
|
68e6c8 |
res->u.attr = git_attr_internal(name, namelen);
|
|
|
68e6c8 |
else {
|
|
|
68e6c8 |
@@ -301,11 +312,11 @@
|
|
|
68e6c8 |
|
|
|
68e6c8 |
static void free_attr_elem(struct attr_stack *e)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
- int i;
|
|
|
68e6c8 |
+ unsigned i;
|
|
|
68e6c8 |
free(e->origin);
|
|
|
68e6c8 |
for (i = 0; i < e->num_matches; i++) {
|
|
|
68e6c8 |
struct match_attr *a = e->attrs[i];
|
|
|
68e6c8 |
- int j;
|
|
|
68e6c8 |
+ size_t j;
|
|
|
68e6c8 |
for (j = 0; j < a->num_attr; j++) {
|
|
|
68e6c8 |
const char *setto = a->state[j].setto;
|
|
|
68e6c8 |
if (setto == ATTR__TRUE ||
|
|
|
68e6c8 |
@@ -364,20 +375,39 @@
|
|
|
68e6c8 |
|
|
|
68e6c8 |
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
+ struct strbuf buf = STRBUF_INIT;
|
|
|
68e6c8 |
FILE *fp = fopen(path, "r");
|
|
|
68e6c8 |
struct attr_stack *res;
|
|
|
68e6c8 |
- char buf[2048];
|
|
|
68e6c8 |
int lineno = 0;
|
|
|
68e6c8 |
+ int fd;
|
|
|
68e6c8 |
+ struct stat st;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
if (!fp) {
|
|
|
68e6c8 |
if (errno != ENOENT && errno != ENOTDIR)
|
|
|
68e6c8 |
warn_on_inaccessible(path);
|
|
|
68e6c8 |
return NULL;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+ fd = fileno(fp);
|
|
|
68e6c8 |
+ if (fstat(fd, &st)) {
|
|
|
68e6c8 |
+ warning_errno(_("cannot fstat gitattributes file '%s'"), path);
|
|
|
68e6c8 |
+ fclose(fp);
|
|
|
68e6c8 |
+ return NULL;
|
|
|
68e6c8 |
+ }
|
|
|
68e6c8 |
+ if (st.st_size >= ATTR_MAX_FILE_SIZE) {
|
|
|
68e6c8 |
+ warning(_("ignoring overly large gitattributes file '%s'"), path);
|
|
|
68e6c8 |
+ fclose(fp);
|
|
|
68e6c8 |
+ return NULL;
|
|
|
68e6c8 |
+ }
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
res = xcalloc(1, sizeof(*res));
|
|
|
68e6c8 |
- while (fgets(buf, sizeof(buf), fp))
|
|
|
68e6c8 |
- handle_attr_line(res, buf, path, ++lineno, macro_ok);
|
|
|
68e6c8 |
+ while (strbuf_getline(&buf, fp, '\n') != EOF) {
|
|
|
68e6c8 |
+ if (!lineno && starts_with(buf.buf, utf8_bom))
|
|
|
68e6c8 |
+ strbuf_remove(&buf, 0, strlen(utf8_bom));
|
|
|
68e6c8 |
+ handle_attr_line(res, buf.buf, path, ++lineno, macro_ok);
|
|
|
68e6c8 |
+ }
|
|
|
68e6c8 |
fclose(fp);
|
|
|
68e6c8 |
+ strbuf_release(&buf;;
|
|
|
68e6c8 |
return res;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
|
|
|
68e6c8 |
@@ -386,11 +416,18 @@
|
|
|
68e6c8 |
struct attr_stack *res;
|
|
|
68e6c8 |
char *buf, *sp;
|
|
|
68e6c8 |
int lineno = 0;
|
|
|
68e6c8 |
+ unsigned long size;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
- buf = read_blob_data_from_index(use_index ? use_index : &the_index, path, NULL);
|
|
|
68e6c8 |
+ buf = read_blob_data_from_index(use_index ? use_index : &the_index, path, &size);
|
|
|
68e6c8 |
if (!buf)
|
|
|
68e6c8 |
return NULL;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
+ if (size >= ATTR_MAX_FILE_SIZE) {
|
|
|
68e6c8 |
+ warning(_("ignoring overly large gitattributes blob '%s'"), path);
|
|
|
68e6c8 |
+ return NULL;
|
|
|
68e6c8 |
+ }
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
res = xcalloc(1, sizeof(*res));
|
|
|
68e6c8 |
for (sp = buf; *sp; ) {
|
|
|
68e6c8 |
char *ep;
|
|
|
68e6c8 |
@@ -648,15 +685,15 @@
|
|
|
68e6c8 |
|
|
|
68e6c8 |
static int macroexpand_one(int attr_nr, int rem);
|
|
|
68e6c8 |
|
|
|
68e6c8 |
-static int fill_one(const char *what, struct match_attr *a, int rem)
|
|
|
68e6c8 |
+static int fill_one(const char *what, const struct match_attr *a, int rem)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
struct git_attr_check *check = check_all_attr;
|
|
|
68e6c8 |
- int i;
|
|
|
68e6c8 |
+ size_t i;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
- for (i = a->num_attr - 1; 0 < rem && 0 <= i; i--) {
|
|
|
68e6c8 |
- struct git_attr *attr = a->state[i].attr;
|
|
|
68e6c8 |
+ for (i = a->num_attr; rem > 0 && i > 0; i--) {
|
|
|
68e6c8 |
+ const struct git_attr *attr = a->state[i - 1].attr;
|
|
|
68e6c8 |
const char **n = &(check[attr->attr_nr].value);
|
|
|
68e6c8 |
- const char *v = a->state[i].setto;
|
|
|
68e6c8 |
+ const char *v = a->state[i - 1].setto;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
if (*n == ATTR__UNKNOWN) {
|
|
|
68e6c8 |
debug_set(what,
|
|
|
68e6c8 |
@@ -673,11 +710,11 @@
|
|
|
68e6c8 |
static int fill(const char *path, int pathlen, int basename_offset,
|
|
|
68e6c8 |
struct attr_stack *stk, int rem)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
- int i;
|
|
|
68e6c8 |
+ unsigned i;
|
|
|
68e6c8 |
const char *base = stk->origin ? stk->origin : "";
|
|
|
68e6c8 |
|
|
|
68e6c8 |
- for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) {
|
|
|
68e6c8 |
- struct match_attr *a = stk->attrs[i];
|
|
|
68e6c8 |
+ for (i = stk->num_matches; 0 < rem && 0 < i; i--) {
|
|
|
68e6c8 |
+ const struct match_attr *a = stk->attrs[i - 1];
|
|
|
68e6c8 |
if (a->is_macro)
|
|
|
68e6c8 |
continue;
|
|
|
68e6c8 |
if (path_matches(path, pathlen, basename_offset,
|
|
|
68e6c8 |
@@ -691,14 +728,14 @@
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
struct attr_stack *stk;
|
|
|
68e6c8 |
struct match_attr *a = NULL;
|
|
|
68e6c8 |
- int i;
|
|
|
68e6c8 |
+ unsigned i;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
if (check_all_attr[attr_nr].value != ATTR__TRUE)
|
|
|
68e6c8 |
return rem;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
for (stk = attr_stack; !a && stk; stk = stk->prev)
|
|
|
68e6c8 |
- for (i = stk->num_matches - 1; !a && 0 <= i; i--) {
|
|
|
68e6c8 |
- struct match_attr *ma = stk->attrs[i];
|
|
|
68e6c8 |
+ for (i = stk->num_matches; !a && i > 0; i--) {
|
|
|
68e6c8 |
+ struct match_attr *ma = stk->attrs[i - 1];
|
|
|
68e6c8 |
if (!ma->is_macro)
|
|
|
68e6c8 |
continue;
|
|
|
68e6c8 |
if (ma->u.attr->attr_nr == attr_nr)
|
|
|
68e6c8 |
diff -ur b/attr.h c/attr.h
|
|
|
68e6c8 |
--- b/attr.h 2013-06-10 22:01:55.000000000 +0200
|
|
|
68e6c8 |
+++ c/attr.h 2023-02-21 12:25:42.455029765 +0100
|
|
|
68e6c8 |
@@ -1,6 +1,18 @@
|
|
|
68e6c8 |
#ifndef ATTR_H
|
|
|
68e6c8 |
#define ATTR_H
|
|
|
68e6c8 |
|
|
|
68e6c8 |
+/**
|
|
|
68e6c8 |
+ * The maximum line length for a gitattributes file. If the line exceeds this
|
|
|
68e6c8 |
+ * length we will ignore it.
|
|
|
68e6c8 |
+ */
|
|
|
68e6c8 |
+#define ATTR_MAX_LINE_LENGTH 2048
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+ /**
|
|
|
68e6c8 |
+ * The maximum size of the giattributes file. If the file exceeds this size we
|
|
|
68e6c8 |
+ * will ignore it.
|
|
|
68e6c8 |
+ */
|
|
|
68e6c8 |
+#define ATTR_MAX_FILE_SIZE (100 * 1024 * 1024)
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
/* An attribute is a pointer to this opaque structure */
|
|
|
68e6c8 |
struct git_attr;
|
|
|
68e6c8 |
|
|
|
68e6c8 |
diff -ur b/git-compat-util.h c/git-compat-util.h
|
|
|
68e6c8 |
--- b/git-compat-util.h 2023-02-21 11:27:58.038145942 +0100
|
|
|
68e6c8 |
+++ c/git-compat-util.h 2023-02-21 12:27:18.836638388 +0100
|
|
|
68e6c8 |
@@ -324,7 +324,9 @@
|
|
|
68e6c8 |
extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
|
|
|
68e6c8 |
extern NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
|
|
|
68e6c8 |
extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
|
|
|
68e6c8 |
+extern int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
|
|
|
68e6c8 |
extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
|
|
|
68e6c8 |
+extern void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
|
|
|
68e6c8 |
|
|
|
68e6c8 |
/*
|
|
|
68e6c8 |
* Let callers be aware of the constant return value; this can help
|
|
|
68e6c8 |
@@ -524,8 +526,8 @@
|
|
|
68e6c8 |
(uintmax_t)a, (uintmax_t)b);
|
|
|
68e6c8 |
return a + b;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
-#define st_add3(a,b,c) st_add((a),st_add((b),(c)))
|
|
|
68e6c8 |
-#define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d)))
|
|
|
68e6c8 |
+#define st_add3(a,b,c) st_add(st_add((a),(b)),(c))
|
|
|
68e6c8 |
+#define st_add4(a,b,c,d) st_add(st_add3((a),(b),(c)),(d))
|
|
|
68e6c8 |
|
|
|
68e6c8 |
static inline size_t st_mult(size_t a, size_t b)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
diff -ur b/t/t0003-attributes.sh c/t/t0003-attributes.sh
|
|
|
68e6c8 |
--- b/t/t0003-attributes.sh 2013-06-10 22:01:55.000000000 +0200
|
|
|
68e6c8 |
+++ c/t/t0003-attributes.sh 2023-02-21 12:30:22.614804084 +0100
|
|
|
68e6c8 |
@@ -245,39 +245,106 @@
|
|
|
68e6c8 |
'
|
|
|
68e6c8 |
|
|
|
68e6c8 |
test_expect_success 'setup bare' '
|
|
|
68e6c8 |
- git clone --bare . bare.git &&
|
|
|
68e6c8 |
- cd bare.git
|
|
|
68e6c8 |
+ git clone --bare . bare.git
|
|
|
68e6c8 |
'
|
|
|
68e6c8 |
|
|
|
68e6c8 |
test_expect_success 'bare repository: check that .gitattribute is ignored' '
|
|
|
68e6c8 |
(
|
|
|
68e6c8 |
- echo "f test=f"
|
|
|
68e6c8 |
- echo "a/i test=a/i"
|
|
|
68e6c8 |
- ) >.gitattributes &&
|
|
|
68e6c8 |
- attr_check f unspecified &&
|
|
|
68e6c8 |
- attr_check a/f unspecified &&
|
|
|
68e6c8 |
- attr_check a/c/f unspecified &&
|
|
|
68e6c8 |
- attr_check a/i unspecified &&
|
|
|
68e6c8 |
- attr_check subdir/a/i unspecified
|
|
|
68e6c8 |
+ cd bare.git &&
|
|
|
68e6c8 |
+ (
|
|
|
68e6c8 |
+ echo "f test=f"
|
|
|
68e6c8 |
+ echo "a/i test=a/i"
|
|
|
68e6c8 |
+ ) >.gitattributes &&
|
|
|
68e6c8 |
+ attr_check f unspecified &&
|
|
|
68e6c8 |
+ attr_check a/f unspecified &&
|
|
|
68e6c8 |
+ attr_check a/c/f unspecified &&
|
|
|
68e6c8 |
+ attr_check a/i unspecified &&
|
|
|
68e6c8 |
+ attr_check subdir/a/i unspecified
|
|
|
68e6c8 |
+ )
|
|
|
68e6c8 |
'
|
|
|
68e6c8 |
|
|
|
68e6c8 |
test_expect_success 'bare repository: check that --cached honors index' '
|
|
|
68e6c8 |
- GIT_INDEX_FILE=../.git/index \
|
|
|
68e6c8 |
- git check-attr --cached --stdin --all <../stdin-all |
|
|
|
68e6c8 |
- sort >actual &&
|
|
|
68e6c8 |
- test_cmp ../specified-all actual
|
|
|
68e6c8 |
+ (
|
|
|
68e6c8 |
+ cd bare.git &&
|
|
|
68e6c8 |
+ GIT_INDEX_FILE=../.git/index \
|
|
|
68e6c8 |
+ git check-attr --cached --stdin --all <../stdin-all |
|
|
|
68e6c8 |
+ sort >actual &&
|
|
|
68e6c8 |
+ test_cmp ../specified-all actual
|
|
|
68e6c8 |
+ )
|
|
|
68e6c8 |
'
|
|
|
68e6c8 |
|
|
|
68e6c8 |
test_expect_success 'bare repository: test info/attributes' '
|
|
|
68e6c8 |
(
|
|
|
68e6c8 |
- echo "f test=f"
|
|
|
68e6c8 |
- echo "a/i test=a/i"
|
|
|
68e6c8 |
- ) >info/attributes &&
|
|
|
68e6c8 |
- attr_check f f &&
|
|
|
68e6c8 |
- attr_check a/f f &&
|
|
|
68e6c8 |
- attr_check a/c/f f &&
|
|
|
68e6c8 |
- attr_check a/i a/i &&
|
|
|
68e6c8 |
- attr_check subdir/a/i unspecified
|
|
|
68e6c8 |
+ cd bare.git &&
|
|
|
68e6c8 |
+ (
|
|
|
68e6c8 |
+ echo "f test=f"
|
|
|
68e6c8 |
+ echo "a/i test=a/i"
|
|
|
68e6c8 |
+ ) >info/attributes &&
|
|
|
68e6c8 |
+ attr_check f f &&
|
|
|
68e6c8 |
+ attr_check a/f f &&
|
|
|
68e6c8 |
+ attr_check a/c/f f &&
|
|
|
68e6c8 |
+ attr_check a/i a/i &&
|
|
|
68e6c8 |
+ attr_check subdir/a/i unspecified
|
|
|
68e6c8 |
+ )
|
|
|
68e6c8 |
+'
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+test_expect_success 'large attributes line ignored in tree' '
|
|
|
68e6c8 |
+ test_when_finished "rm .gitattributes" &&
|
|
|
68e6c8 |
+ printf "path %02043d" 1 >.gitattributes &&
|
|
|
68e6c8 |
+ git check-attr --all path >actual 2>err &&
|
|
|
68e6c8 |
+ echo "warning: ignoring overly long attributes line 1" >expect &&
|
|
|
68e6c8 |
+ test_cmp expect err &&
|
|
|
68e6c8 |
+ test_must_be_empty actual
|
|
|
68e6c8 |
+'
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+test_expect_success 'large attributes line ignores trailing content in tree' '
|
|
|
68e6c8 |
+ test_when_finished "rm .gitattributes" &&
|
|
|
68e6c8 |
+ # older versions of Git broke lines at 2048 bytes; the 2045 bytes
|
|
|
68e6c8 |
+ # of 0-padding here is accounting for the three bytes of "a 1", which
|
|
|
68e6c8 |
+ # would knock "trailing" to the "next" line, where it would be
|
|
|
68e6c8 |
+ # erroneously parsed.
|
|
|
68e6c8 |
+ printf "a %02045dtrailing attribute\n" 1 >.gitattributes &&
|
|
|
68e6c8 |
+ git check-attr --all trailing >actual 2>err &&
|
|
|
68e6c8 |
+ echo "warning: ignoring overly long attributes line 1" >expect &&
|
|
|
68e6c8 |
+ test_cmp expect err &&
|
|
|
68e6c8 |
+ test_must_be_empty actual
|
|
|
68e6c8 |
+'
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+test_expect_success EXPENSIVE 'large attributes file ignored in tree' '
|
|
|
68e6c8 |
+ test_when_finished "rm .gitattributes" &&
|
|
|
68e6c8 |
+ dd if=/dev/zero of=.gitattributes bs=101M count=1 2>/dev/null &&
|
|
|
68e6c8 |
+ git check-attr --all path >/dev/null 2>err &&
|
|
|
68e6c8 |
+ echo "warning: ignoring overly large gitattributes file ${SQ}.gitattributes${SQ}" >expect &&
|
|
|
68e6c8 |
+ test_cmp expect err
|
|
|
68e6c8 |
+'
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+test_expect_success 'large attributes line ignored in index' '
|
|
|
68e6c8 |
+ test_when_finished "git update-index --remove .gitattributes" &&
|
|
|
68e6c8 |
+ blob=$(printf "path %02043d" 1 | git hash-object -w --stdin) &&
|
|
|
68e6c8 |
+ git update-index --add --cacheinfo 100644 $blob .gitattributes &&
|
|
|
68e6c8 |
+ git check-attr --cached --all path >actual 2>err &&
|
|
|
68e6c8 |
+ echo "warning: ignoring overly long attributes line 1" >expect &&
|
|
|
68e6c8 |
+ test_cmp expect err &&
|
|
|
68e6c8 |
+ test_must_be_empty actual
|
|
|
68e6c8 |
+'
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+test_expect_success 'large attributes line ignores trailing content in index' '
|
|
|
68e6c8 |
+ test_when_finished "git update-index --remove .gitattributes" &&
|
|
|
68e6c8 |
+ blob=$(printf "a %02045dtrailing attribute\n" 1 | git hash-object -w --stdin) &&
|
|
|
68e6c8 |
+ git update-index --add --cacheinfo 100644 $blob .gitattributes &&
|
|
|
68e6c8 |
+ git check-attr --cached --all trailing >actual 2>err &&
|
|
|
68e6c8 |
+ echo "warning: ignoring overly long attributes line 1" >expect &&
|
|
|
68e6c8 |
+ test_cmp expect err &&
|
|
|
68e6c8 |
+ test_must_be_empty actual
|
|
|
68e6c8 |
+'
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+test_expect_success EXPENSIVE 'large attributes file ignored in index' '
|
|
|
68e6c8 |
+ test_when_finished "git update-index --remove .gitattributes" &&
|
|
|
68e6c8 |
+ blob=$(dd if=/dev/zero bs=101M count=1 2>/dev/null | git hash-object -w --stdin) &&
|
|
|
68e6c8 |
+ git update-index --add --cacheinfo 100644 $blob .gitattributes &&
|
|
|
68e6c8 |
+ git check-attr --cached --all path >/dev/null 2>err &&
|
|
|
68e6c8 |
+ echo "warning: ignoring overly large gitattributes blob ${SQ}.gitattributes${SQ}" >expect &&
|
|
|
68e6c8 |
+ test_cmp expect err
|
|
|
68e6c8 |
'
|
|
|
68e6c8 |
|
|
|
68e6c8 |
test_done
|
|
|
68e6c8 |
diff -ur b/t/test-lib-functions.sh c/t/test-lib-functions.sh
|
|
|
68e6c8 |
--- b/t/test-lib-functions.sh 2013-06-10 22:01:55.000000000 +0200
|
|
|
68e6c8 |
+++ c/t/test-lib-functions.sh 2023-02-21 12:31:24.357204323 +0100
|
|
|
68e6c8 |
@@ -609,6 +609,20 @@
|
|
|
68e6c8 |
$GIT_TEST_CMP "$@"
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
|
|
|
68e6c8 |
+# Check if the file expected to be empty is indeed empty, and barfs
|
|
|
68e6c8 |
+# otherwise.
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+test_must_be_empty () {
|
|
|
68e6c8 |
+ test "$#" -ne 1 && BUG "1 param"
|
|
|
68e6c8 |
+ test_path_is_file "$1" &&
|
|
|
68e6c8 |
+ if test -s "$1"
|
|
|
68e6c8 |
+ then
|
|
|
68e6c8 |
+ echo "'$1' is not empty, it contains:"
|
|
|
68e6c8 |
+ cat "$1"
|
|
|
68e6c8 |
+ return 1
|
|
|
68e6c8 |
+ fi
|
|
|
68e6c8 |
+}
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
# Tests that its two parameters refer to the same revision
|
|
|
68e6c8 |
test_cmp_rev () {
|
|
|
68e6c8 |
git rev-parse --verify "$1" >expect.rev &&
|
|
|
68e6c8 |
diff -ur b/t/test-lib.sh c/t/test-lib.sh
|
|
|
68e6c8 |
--- b/t/test-lib.sh 2023-02-21 11:52:24.739202530 +0100
|
|
|
68e6c8 |
+++ c/t/test-lib.sh 2023-02-21 12:31:52.866389106 +0100
|
|
|
68e6c8 |
@@ -153,6 +153,9 @@
|
|
|
68e6c8 |
LF='
|
|
|
68e6c8 |
'
|
|
|
68e6c8 |
|
|
|
68e6c8 |
+# Single quote
|
|
|
68e6c8 |
+SQ=\'
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
export _x05 _x40 _z40 LF
|
|
|
68e6c8 |
|
|
|
68e6c8 |
# Each test should start with something like this, after copyright notices:
|
|
|
68e6c8 |
diff -ur b/usage.c c/usage.c
|
|
|
68e6c8 |
--- b/usage.c 2013-06-10 22:01:55.000000000 +0200
|
|
|
68e6c8 |
+++ c/usage.c 2023-02-21 12:32:56.807803579 +0100
|
|
|
68e6c8 |
@@ -104,6 +104,30 @@
|
|
|
68e6c8 |
va_end(params);
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
|
|
|
68e6c8 |
+static const char *fmt_with_err(char *buf, int n, const char *fmt)
|
|
|
68e6c8 |
+{
|
|
|
68e6c8 |
+ char str_error[256], *err;
|
|
|
68e6c8 |
+ int i, j;
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+ err = strerror(errno);
|
|
|
68e6c8 |
+ for (i = j = 0; err[i] && j < sizeof(str_error) - 1; ) {
|
|
|
68e6c8 |
+ if ((str_error[j++] = err[i++]) != '%')
|
|
|
68e6c8 |
+ continue;
|
|
|
68e6c8 |
+ if (j < sizeof(str_error) - 1) {
|
|
|
68e6c8 |
+ str_error[j++] = '%';
|
|
|
68e6c8 |
+ } else {
|
|
|
68e6c8 |
+ /* No room to double the '%', so we overwrite it with
|
|
|
68e6c8 |
+ * '\0' below */
|
|
|
68e6c8 |
+ j--;
|
|
|
68e6c8 |
+ break;
|
|
|
68e6c8 |
+ }
|
|
|
68e6c8 |
+ }
|
|
|
68e6c8 |
+ str_error[j] = 0;
|
|
|
68e6c8 |
+ /* Truncation is acceptable here */
|
|
|
68e6c8 |
+ snprintf(buf, n, "%s: %s", fmt, str_error);
|
|
|
68e6c8 |
+ return buf;
|
|
|
68e6c8 |
+}
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
void NORETURN die_errno(const char *fmt, ...)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
va_list params;
|
|
|
68e6c8 |
@@ -149,6 +173,16 @@
|
|
|
68e6c8 |
return -1;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
|
|
|
68e6c8 |
+void warning_errno(const char *warn, ...)
|
|
|
68e6c8 |
+{
|
|
|
68e6c8 |
+ char buf[1024];
|
|
|
68e6c8 |
+ va_list params;
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+ va_start(params, warn);
|
|
|
68e6c8 |
+ warn_routine(fmt_with_err(buf, sizeof(buf), warn), params);
|
|
|
68e6c8 |
+ va_end(params);
|
|
|
68e6c8 |
+}
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
void warning(const char *warn, ...)
|
|
|
68e6c8 |
{
|
|
|
68e6c8 |
va_list params;
|
|
|
68e6c8 |
diff -ur b/utf8.c c/utf8.c
|
|
|
68e6c8 |
--- b/utf8.c 2023-02-21 12:00:28.555925285 +0100
|
|
|
68e6c8 |
+++ c/utf8.c 2023-02-21 12:33:48.863141018 +0100
|
|
|
68e6c8 |
@@ -639,3 +639,14 @@
|
|
|
68e6c8 |
|
|
|
68e6c8 |
return chrlen;
|
|
|
68e6c8 |
}
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+const char utf8_bom[] = "\357\273\277";
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
+int skip_utf8_bom(char **text, size_t len)
|
|
|
68e6c8 |
+{
|
|
|
68e6c8 |
+ if (len < strlen(utf8_bom) ||
|
|
|
68e6c8 |
+ memcmp(*text, utf8_bom, strlen(utf8_bom)))
|
|
|
68e6c8 |
+ return 0;
|
|
|
68e6c8 |
+ *text += strlen(utf8_bom);
|
|
|
68e6c8 |
+ return 1;
|
|
|
68e6c8 |
+}
|
|
|
68e6c8 |
diff -ur b/utf8.h c/utf8.h
|
|
|
68e6c8 |
--- b/utf8.h 2023-02-21 12:00:40.186991497 +0100
|
|
|
68e6c8 |
+++ c/utf8.h 2023-02-21 12:34:19.536339834 +0100
|
|
|
68e6c8 |
@@ -12,6 +12,9 @@
|
|
|
68e6c8 |
int same_encoding(const char *, const char *);
|
|
|
68e6c8 |
int utf8_fprintf(FILE *, const char *, ...);
|
|
|
68e6c8 |
|
|
|
68e6c8 |
+extern const char utf8_bom[];
|
|
|
68e6c8 |
+int skip_utf8_bom(char **, size_t);
|
|
|
68e6c8 |
+
|
|
|
68e6c8 |
void strbuf_add_wrapped_text(struct strbuf *buf,
|
|
|
68e6c8 |
const char *text, int indent, int indent2, int width);
|
|
|
68e6c8 |
void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
|