use xsnprintf for generating git object headers

We generally use 32-byte buffers to format git's "type size" header fields. These should not generally overflow unless you can produce some truly gigantic objects (and our types come from our internal array of constant strings). But it is a good idea to use xsnprintf to make sure this is the case. Note that we slightly modify the interface to write_sha1_file_prepare, which nows uses "hdrlen" as an "in" parameter as well as an "out" (on the way in it stores the allocated size of the header, and on the way out it returns the ultimate size of the header). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Sep 24, 2015 at 17:06 UTC ef1286d3c0ba714c6c2ae87e14edf3c462aef114
5 files changed +13 -12
builtin/index-pack.c
+1 -1
@@ -441,7 +441,7 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size,
441 int hdrlen;
442
443 if (!is_delta_type(type)) {
444 - hdrlen = sprintf(hdr, "%s %lu", typename(type), size) + 1;
444 + hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(type), size) + 1;
445 git_SHA1_Init(&c);
446 git_SHA1_Update(&c, hdr, hdrlen);
447 } else
bulk-checkin.c
+2 -2
@@ -200,8 +200,8 @@ static int deflate_to_pack(struct bulk_checkin_state *state,
200 if (seekback == (off_t) -1)
201 return error("cannot find the current offset");
202
203 - header_len = sprintf((char *)obuf, "%s %" PRIuMAX,
204 - typename(type), (uintmax_t)size) + 1;
203 + header_len = xsnprintf((char *)obuf, sizeof(obuf), "%s %" PRIuMAX,
204 + typename(type), (uintmax_t)size) + 1;
205 git_SHA1_Init(&ctx);
206 git_SHA1_Update(&ctx, obuf, header_len);
207
fast-import.c
+2 -2
@@ -1035,8 +1035,8 @@ static int store_object(
1035 git_SHA_CTX c;
1036 git_zstream s;
1037
1038 - hdrlen = sprintf((char *)hdr,"%s %lu", typename(type),
1039 - (unsigned long)dat->len) + 1;
1038 + hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu",
1039 + typename(type), (unsigned long)dat->len) + 1;
1040 git_SHA1_Init(&c);
1041 git_SHA1_Update(&c, hdr, hdrlen);
1042 git_SHA1_Update(&c, dat->buf, dat->len);
http-push.c
+1 -1
@@ -361,7 +361,7 @@ static void start_put(struct transfer_request *request)
361 git_zstream stream;
362
363 unpacked = read_sha1_file(request->obj->sha1, &type, &len);
364 - hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1;
364 + hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(type), len) + 1;
365
366 /* Set it up */
367 git_deflate_init(&stream, zlib_compression_level);
sha1_file.c
+7 -6
@@ -1464,7 +1464,7 @@ int check_sha1_signature(const unsigned char *sha1, void *map,
1464 return -1;
1465
1466 /* Generate the header */
1467 - hdrlen = sprintf(hdr, "%s %lu", typename(obj_type), size) + 1;
1467 + hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(obj_type), size) + 1;
1468
1469 /* Sha1.. */
1470 git_SHA1_Init(&c);
@@ -2930,7 +2930,7 @@ static void write_sha1_file_prepare(const void *buf, unsigned long len,
2930 git_SHA_CTX c;
2931
2932 /* Generate the header */
2933 - *hdrlen = sprintf(hdr, "%s %lu", type, len)+1;
2933 + *hdrlen = xsnprintf(hdr, *hdrlen, "%s %lu", type, len)+1;
2934
2935 /* Sha1.. */
2936 git_SHA1_Init(&c);
@@ -2993,7 +2993,7 @@ int hash_sha1_file(const void *buf, unsigned long len, const char *type,
2993 unsigned char *sha1)
2994 {
2995 char hdr[32];
2996 - int hdrlen;
2996 + int hdrlen = sizeof(hdr);
2997 write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen);
2998 return 0;
2999 }
@@ -3139,7 +3139,7 @@ static int freshen_packed_object(const unsigned char *sha1)
3139 int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1)
3140 {
3141 char hdr[32];
3142 - int hdrlen;
3142 + int hdrlen = sizeof(hdr);
3143
3144 /* Normally if we have it in the pack then we do not bother writing
3145 * it out into .git/objects/??/?{38} file.
@@ -3157,7 +3157,8 @@ int hash_sha1_file_literally(const void *buf, unsigned long len, const char *typ
3157 int hdrlen, status = 0;
3158
3159 /* type string, SP, %lu of the length plus NUL must fit this */
3160 - header = xmalloc(strlen(type) + 32);
3160 + hdrlen = strlen(type) + 32;
3161 + header = xmalloc(hdrlen);
3162 write_sha1_file_prepare(buf, len, type, sha1, header, &hdrlen);
3163
3164 if (!(flags & HASH_WRITE_OBJECT))
@@ -3185,7 +3186,7 @@ int force_object_loose(const unsigned char *sha1, time_t mtime)
3186 buf = read_packed_sha1(sha1, &type, &len);
3187 if (!buf)
3188 return error("cannot read sha1_file for %s", sha1_to_hex(sha1));
3188 - hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1;
3189 + hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", typename(type), len) + 1;
3190 ret = write_loose_object(sha1, hdr, hdrlen, buf, len, mtime);
3191 free(buf);
3192