summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: cf7b1ca)
raw | patch | inline | side by side (parent: cf7b1ca)
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | |
Sat, 5 Feb 2011 10:52:21 +0000 (17:52 +0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Mon, 7 Feb 2011 23:05:25 +0000 (15:05 -0800) |
Commits, trees and tags have structure. Don't let users feed git
with malformed ones. Sooner or later git will die() when
encountering them.
Note that this patch does not check semantics. A tree that points
to non-existent objects is perfectly OK (and should be so, users
may choose to add commit first, then its associated tree for example).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
with malformed ones. Sooner or later git will die() when
encountering them.
Note that this patch does not check semantics. A tree that points
to non-existent objects is perfectly OK (and should be so, users
may choose to add commit first, then its associated tree for example).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/hash-object.c | patch | blob | history | |
cache.h | patch | blob | history | |
read-cache.c | patch | blob | history | |
sha1_file.c | patch | blob | history | |
t/t1007-hash-object.sh | patch | blob | history |
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 080af1a01b8155680faf6c04101217b60ae7b919..c90acddcb2c32ce5170a220c9b1af96b44552a41 100644 (file)
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
struct stat st;
unsigned char sha1[20];
if (fstat(fd, &st) < 0 ||
- index_fd(sha1, fd, &st, write_object, type_from_string(type), path))
+ index_fd(sha1, fd, &st, write_object, type_from_string(type), path, 1))
die(write_object
? "Unable to add %s to database"
: "Unable to hash %s", path);
index d83d68c859904fadbe2501cabd8575be09131d7b..9186a56be7309261289222dc8e9726439e550233 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -501,7 +501,7 @@ extern int ie_match_stat(const struct index_state *, struct cache_entry *, struc
extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
-extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
+extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path, int format_check);
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
diff --git a/read-cache.c b/read-cache.c
index 4f2e890b01b0c27ef2e49080e1fd34bf67e969c7..fbc12f3c3e8aac2c0d15d57b023315ce4d5156f6 100644 (file)
--- a/read-cache.c
+++ b/read-cache.c
if (fd >= 0) {
unsigned char sha1[20];
- if (!index_fd(sha1, fd, st, 0, OBJ_BLOB, ce->name))
+ if (!index_fd(sha1, fd, st, 0, OBJ_BLOB, ce->name, 0))
match = hashcmp(sha1, ce->sha1);
/* index_fd() closed the file descriptor already */
}
diff --git a/sha1_file.c b/sha1_file.c
index d86a8db69ade6fd26ebd88bbb361a7a86838f14e..58ca85835b6d5d8d45c195139c594711dcac2228 100644 (file)
--- a/sha1_file.c
+++ b/sha1_file.c
#include "commit.h"
#include "tag.h"
#include "tree.h"
+#include "tree-walk.h"
#include "refs.h"
#include "pack-revindex.h"
#include "sha1-lookup.h"
return has_loose_object(sha1);
}
+static void check_tree(const void *buf, size_t size)
+{
+ struct tree_desc desc;
+ struct name_entry entry;
+
+ init_tree_desc(&desc, buf, size);
+ while (tree_entry(&desc, &entry))
+ /* do nothing
+ * tree_entry() will die() on malformed entries */
+ ;
+}
+
+static void check_commit(const void *buf, size_t size)
+{
+ struct commit c;
+ memset(&c, 0, sizeof(c));
+ if (parse_commit_buffer(&c, buf, size))
+ die("corrupt commit");
+}
+
+static void check_tag(const void *buf, size_t size)
+{
+ struct tag t;
+ memset(&t, 0, sizeof(t));
+ if (parse_tag_buffer(&t, buf, size))
+ die("corrupt tag");
+}
+
static int index_mem(unsigned char *sha1, void *buf, size_t size,
- int write_object, enum object_type type, const char *path)
+ int write_object, enum object_type type,
+ const char *path, int format_check)
{
int ret, re_allocated = 0;
re_allocated = 1;
}
}
+ if (format_check) {
+ if (type == OBJ_TREE)
+ check_tree(buf, size);
+ if (type == OBJ_COMMIT)
+ check_commit(buf, size);
+ if (type == OBJ_TAG)
+ check_tag(buf, size);
+ }
if (write_object)
ret = write_sha1_file(buf, size, typename(type), sha1);
#define SMALL_FILE_SIZE (32*1024)
int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
- enum object_type type, const char *path)
+ enum object_type type, const char *path, int format_check)
{
int ret;
size_t size = xsize_t(st->st_size);
@@ -2512,23 +2550,25 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
struct strbuf sbuf = STRBUF_INIT;
if (strbuf_read(&sbuf, fd, 4096) >= 0)
ret = index_mem(sha1, sbuf.buf, sbuf.len, write_object,
- type, path);
+ type, path, format_check);
else
ret = -1;
strbuf_release(&sbuf);
} else if (!size) {
- ret = index_mem(sha1, NULL, size, write_object, type, path);
+ ret = index_mem(sha1, NULL, size, write_object, type, path,
+ format_check);
} else if (size <= SMALL_FILE_SIZE) {
char *buf = xmalloc(size);
if (size == read_in_full(fd, buf, size))
ret = index_mem(sha1, buf, size, write_object, type,
- path);
+ path, format_check);
else
ret = error("short read %s", strerror(errno));
free(buf);
} else {
void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
- ret = index_mem(sha1, buf, size, write_object, type, path);
+ ret = index_mem(sha1, buf, size, write_object, type, path,
+ format_check);
munmap(buf, size);
}
close(fd);
@@ -2546,7 +2586,7 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
if (fd < 0)
return error("open(\"%s\"): %s", path,
strerror(errno));
- if (index_fd(sha1, fd, st, write_object, OBJ_BLOB, path) < 0)
+ if (index_fd(sha1, fd, st, write_object, OBJ_BLOB, path, 0) < 0)
return error("%s: failed to insert into database",
path);
break;
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index dd32432d626e4f3d192c2bbe4824772025bb08b1..6d52b824b115964c5551aaf4284205b98b885ce3 100755 (executable)
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
pop_repo
done
+test_expect_success 'corrupt tree' '
+ echo abc >malformed-tree
+ test_must_fail git hash-object -t tree malformed-tree
+'
+
+test_expect_success 'corrupt commit' '
+ test_must_fail git hash-object -t commit --stdin </dev/null
+'
+
+test_expect_success 'corrupt tag' '
+ test_must_fail git hash-object -t tag --stdin </dev/null
+'
+
test_done