Change the functions to do with passing the type down to hash_object_file_literally() to pass the length of the type as well as the "const char *" type name. The immediate motivation for this is to move hash-object.c over to type_from_string_gently() to emit a better error message, but it will also allow us in the future to craft an invalid object with a "\0" in the type name. We'd need to learn a --type-file=* option or similar (we can't of course, pass a string with "\0" on the command-line). Right now such an object can be manually crafted, but we can't test for it with --literally. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@xxxxxxxxx> --- builtin/hash-object.c | 31 +++++++++++++++++-------------- object-file.c | 26 +++++++++++++++----------- object-store.h | 4 ++-- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 640ef4ded5..4d3b8c49d2 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -25,14 +25,14 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig if (strbuf_read(&buf, fd, 4096) < 0) ret = -1; else - ret = hash_object_file_literally(buf.buf, buf.len, type, oid, - flags); + ret = hash_object_file_literally(buf.buf, buf.len, type, + strlen(type), oid, flags); strbuf_release(&buf); return ret; } -static void hash_fd(int fd, const char *type, const char *path, unsigned flags, - int literally) +static void hash_fd(int fd, const char *type, size_t type_len, + const char *path, unsigned flags, int literally) { struct stat st; struct object_id oid; @@ -49,31 +49,32 @@ static void hash_fd(int fd, const char *type, const char *path, unsigned flags, maybe_flush_or_die(stdout, "hash to stdout"); } -static void hash_object(const char *path, const char *type, const char *vpath, - unsigned flags, int literally) +static void hash_object(const char *path, const char *type, size_t type_len, + const char *vpath, unsigned flags, int literally) { int fd; fd = open(path, O_RDONLY); if (fd < 0) die_errno("Cannot open '%s'", path); - hash_fd(fd, type, vpath, flags, literally); + hash_fd(fd, type, type_len, vpath, flags, literally); } -static void hash_stdin_paths(const char *type, int no_filters, unsigned flags, - int literally) +static void hash_stdin_paths(const char *type, size_t type_len, int no_filters, + unsigned flags, int literally) { struct strbuf buf = STRBUF_INIT; struct strbuf unquoted = STRBUF_INIT; while (strbuf_getline(&buf, stdin) != EOF) { + const char *vpath; if (buf.buf[0] == '"') { strbuf_reset(&unquoted); if (unquote_c_style(&unquoted, buf.buf, NULL)) die("line is badly quoted"); strbuf_swap(&buf, &unquoted); } - hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags, - literally); + vpath = no_filters ? NULL : buf.buf; + hash_object(buf.buf, type, type_len, vpath , flags, literally); } strbuf_release(&buf); strbuf_release(&unquoted); @@ -87,6 +88,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) NULL }; const char *type = blob_type; + size_t type_len; int hashstdin = 0; int stdin_paths = 0; int no_filters = 0; @@ -141,8 +143,9 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) usage_with_options(hash_object_usage, hash_object_options); } + type_len = strlen(type); if (hashstdin) - hash_fd(0, type, vpath, flags, literally); + hash_fd(0, type, type_len, vpath, flags, literally); for (i = 0 ; i < argc; i++) { const char *arg = argv[i]; @@ -150,13 +153,13 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) if (prefix) arg = to_free = prefix_filename(prefix, arg); - hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg, + hash_object(arg, type, type_len, no_filters ? NULL : vpath ? vpath : arg, flags, literally); free(to_free); } if (stdin_paths) - hash_stdin_paths(type, no_filters, flags, literally); + hash_stdin_paths(type, type_len, no_filters, flags, literally); return 0; } diff --git a/object-file.c b/object-file.c index 398f2b60f9..b27ed57e0b 100644 --- a/object-file.c +++ b/object-file.c @@ -1715,13 +1715,15 @@ void *read_object_with_reference(struct repository *r, static void write_object_file_prepare(const struct git_hash_algo *algo, const void *buf, unsigned long len, - const char *type, struct object_id *oid, - char *hdr, int *hdrlen) + const char *type, size_t type_len, + struct object_id *oid, char *hdr, + int *hdrlen) { git_hash_ctx c; /* Generate the header */ - *hdrlen = xsnprintf(hdr, *hdrlen, "%s %"PRIuMAX , type, (uintmax_t)len)+1; + *hdrlen = xsnprintf(hdr, *hdrlen, "%.*s %"PRIuMAX, + (int)type_len, type, (uintmax_t)len) + 1; /* Sha1.. */ algo->init_fn(&c); @@ -1786,7 +1788,8 @@ int hash_object_file(const struct git_hash_algo *algo, const void *buf, { char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); - write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); + write_object_file_prepare(algo, buf, len, type, strlen(type), oid, hdr, + &hdrlen); return 0; } @@ -1940,29 +1943,30 @@ int write_object_file(const void *buf, unsigned long len, const char *type, { char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); + size_t type_len = strlen(type); /* Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. */ - write_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr, - &hdrlen); + write_object_file_prepare(the_hash_algo, buf, len, type, type_len, oid, + hdr, &hdrlen); if (freshen_packed_object(oid) || freshen_loose_object(oid)) return 0; return write_loose_object(oid, hdr, hdrlen, buf, len, 0); } int hash_object_file_literally(const void *buf, unsigned long len, - const char *type, struct object_id *oid, - unsigned flags) + const char *type, size_t type_len, + struct object_id *oid, unsigned flags) { char *header; int hdrlen, status = 0; /* type string, SP, %lu of the length plus NUL must fit this */ - hdrlen = strlen(type) + MAX_HEADER_LEN; + hdrlen = type_len + MAX_HEADER_LEN; header = xmalloc(hdrlen); - write_object_file_prepare(the_hash_algo, buf, len, type, oid, header, - &hdrlen); + write_object_file_prepare(the_hash_algo, buf, len, type, type_len, oid, + header, &hdrlen); if (!(flags & HASH_WRITE_OBJECT)) goto cleanup; diff --git a/object-store.h b/object-store.h index eab9674d08..8f043a6069 100644 --- a/object-store.h +++ b/object-store.h @@ -220,8 +220,8 @@ int write_object_file(const void *buf, unsigned long len, const char *type, struct object_id *oid); int hash_object_file_literally(const void *buf, unsigned long len, - const char *type, struct object_id *oid, - unsigned flags); + const char *type, size_t type_len, + struct object_id *oid, unsigned flags); /* * Add an object file to the in-memory object store, without writing it -- 2.31.1.723.ga5d7868e4a