From: Junio C Hamano Date: Mon, 11 May 2015 21:23:59 +0000 (-0700) Subject: Merge branch 'jc/hash-object' X-Git-Tag: v2.5.0-rc0~122 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/051086b947ee7a6fdd5697889a225098f723761d Merge branch 'jc/hash-object' "hash-object --literally" introduced in v2.2 was not prepared to take a really long object type name. * jc/hash-object: write_sha1_file(): do not use a separate sha1[] array t1007: add hash-object --literally tests hash-object --literally: fix buffer overrun with extra-long object type git-hash-object.txt: document --literally option --- 051086b947ee7a6fdd5697889a225098f723761d diff --cc sha1_file.c index 7634917e4e,5d320753c3..866021b2b1 --- a/sha1_file.c +++ b/sha1_file.c @@@ -2989,27 -2945,8 +2989,26 @@@ static int write_loose_object(const uns return move_temp_to_file(tmp_file, filename); } +static int freshen_loose_object(const unsigned char *sha1) +{ + return check_and_freshen(sha1, 1); +} + +static int freshen_packed_object(const unsigned char *sha1) +{ + struct pack_entry e; + if (!find_pack_entry(sha1, &e)) + return 0; + if (e.p->freshened) + return 1; + if (!freshen_file(e.p->pack_name)) + return 0; + e.p->freshened = 1; + return 1; +} + - int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *returnsha1) + int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1) { - unsigned char sha1[20]; char hdr[32]; int hdrlen; @@@ -3017,13 -2954,32 +3016,32 @@@ * it out into .git/objects/??/?{38} file. */ write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen); - if (returnsha1) - hashcpy(returnsha1, sha1); - if (has_sha1_file(sha1)) + if (freshen_packed_object(sha1) || freshen_loose_object(sha1)) return 0; return write_loose_object(sha1, hdr, hdrlen, buf, len, 0); } + int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, + unsigned char *sha1, unsigned flags) + { + char *header; + int hdrlen, status = 0; + + /* type string, SP, %lu of the length plus NUL must fit this */ + header = xmalloc(strlen(type) + 32); + write_sha1_file_prepare(buf, len, type, sha1, header, &hdrlen); + + if (!(flags & HASH_WRITE_OBJECT)) + goto cleanup; - if (has_sha1_file(sha1)) ++ if (freshen_packed_object(sha1) || freshen_loose_object(sha1)) + goto cleanup; + status = write_loose_object(sha1, header, hdrlen, buf, len, 0); + + cleanup: + free(header); + return status; + } + int force_object_loose(const unsigned char *sha1, time_t mtime) { void *buf; diff --cc t/t1007-hash-object.sh index ebb3a69c8c,7c3dcfb70c..7d2baa15bb --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@@ -201,12 -201,15 +201,23 @@@ test_expect_success 'corrupt tag' test_must_fail git hash-object -t tag --stdin