diff options
| author | Edward Thomson <ethomson@edwardthomson.com> | 2018-02-09 13:56:23 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-02-09 13:56:23 +0000 |
| commit | 028a28066ff3aaf79767e9a5c5cc5ff6762cc4bc (patch) | |
| tree | 39c2b6cb22868e04d5ccb5f334331a6554fed3a0 /src/odb.c | |
| parent | 0fd0bfe435989b4947babfcd61b0bf573ff41e28 (diff) | |
| parent | 9985edb579b75c40e33af1c42415c90fc669b73f (diff) | |
| download | libgit2-028a28066ff3aaf79767e9a5c5cc5ff6762cc4bc.tar.gz | |
Merge pull request #4509 from libgit2/ethomson/odb_alloc_error
odb: error when we can't alloc an object
Diffstat (limited to 'src/odb.c')
| -rw-r--r-- | src/odb.c | 101 |
1 files changed, 68 insertions, 33 deletions
@@ -66,50 +66,75 @@ static git_otype odb_hardcoded_type(const git_oid *id) return GIT_OBJ_BAD; } -static int odb_read_hardcoded(git_rawobj *raw, const git_oid *id) +static int odb_read_hardcoded(bool *found, git_rawobj *raw, const git_oid *id) { - git_otype type = odb_hardcoded_type(id); - if (type == GIT_OBJ_BAD) - return -1; + git_otype type; + + *found = false; + + if ((type = odb_hardcoded_type(id)) == GIT_OBJ_BAD) + return 0; raw->type = type; raw->len = 0; raw->data = git__calloc(1, sizeof(uint8_t)); + GITERR_CHECK_ALLOC(raw->data); + + *found = true; return 0; } -int git_odb__format_object_header(char *hdr, size_t n, git_off_t obj_len, git_otype obj_type) +int git_odb__format_object_header( + size_t *written, + char *hdr, + size_t hdr_size, + git_off_t obj_len, + git_otype obj_type) { const char *type_str = git_object_type2string(obj_type); - int len = p_snprintf(hdr, n, "%s %lld", type_str, (long long)obj_len); - assert(len > 0 && len <= (int)n); - return len+1; + int hdr_max = (hdr_size > INT_MAX-2) ? (INT_MAX-2) : (int)hdr_size; + int len; + + len = p_snprintf(hdr, hdr_max, "%s %lld", type_str, (long long)obj_len); + + if (len < 0 || len >= hdr_max) { + giterr_set(GITERR_OS, "object header creation failed"); + return -1; + } + + *written = (size_t)(len + 1); + return 0; } int git_odb__hashobj(git_oid *id, git_rawobj *obj) { git_buf_vec vec[2]; char header[64]; - int hdrlen; + size_t hdrlen; + int error; assert(id && obj); - if (!git_object_typeisloose(obj->type)) + if (!git_object_typeisloose(obj->type)) { + giterr_set(GITERR_INVALID, "invalid object type"); return -1; + } - if (!obj->data && obj->len != 0) + if (!obj->data && obj->len != 0) { + giterr_set(GITERR_INVALID, "invalid object"); return -1; + } - hdrlen = git_odb__format_object_header(header, sizeof(header), obj->len, obj->type); + if ((error = git_odb__format_object_header(&hdrlen, + header, sizeof(header), obj->len, obj->type)) < 0) + return error; vec[0].data = header; vec[0].len = hdrlen; vec[1].data = obj->data; vec[1].len = obj->len; - git_hash_vec(id, vec, 2); - - return 0; + return git_hash_vec(id, vec, 2); } @@ -172,7 +197,7 @@ void git_odb_object_free(git_odb_object *object) int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) { - int hdr_len; + size_t hdr_len; char hdr[64], buffer[FILEIO_BUFSIZE]; git_hash_ctx ctx; ssize_t read_len = 0; @@ -184,9 +209,11 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) } if ((error = git_hash_ctx_init(&ctx)) < 0) - return -1; + return error; - hdr_len = git_odb__format_object_header(hdr, sizeof(hdr), size, type); + if ((error = git_odb__format_object_header(&hdr_len, hdr, + sizeof(hdr), size, type)) < 0) + goto done; if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0) goto done; @@ -342,8 +369,7 @@ static int fake_wstream__write(git_odb_stream *_stream, const char *data, size_t { fake_wstream *stream = (fake_wstream *)_stream; - if (stream->written + len > stream->size) - return -1; + assert(stream->written + len > stream->size); memcpy(stream->buffer + stream->written, data, len); stream->written += len; @@ -800,7 +826,7 @@ int git_odb_exists_prefix( git_oid *out, git_odb *db, const git_oid *short_id, size_t len) { int error; - git_oid key = {{0}}; + git_oid key = {{0}}; assert(db && short_id); @@ -1012,8 +1038,10 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id, bool found = false; int error = 0; - if (!only_refreshed && odb_read_hardcoded(&raw, id) == 0) - found = true; + if (!only_refreshed) { + if ((error = odb_read_hardcoded(&found, &raw, id)) < 0) + return error; + } for (i = 0; i < db->backends.length && !found; ++i) { backend_internal *internal = git_vector_get(&db->backends, i); @@ -1048,8 +1076,10 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id, } giterr_clear(); - if ((object = odb_object__alloc(id, &raw)) == NULL) + if ((object = odb_object__alloc(id, &raw)) == NULL) { + error = -1; goto out; + } *out = git_cache_store_raw(odb_cache(db), object); @@ -1096,7 +1126,7 @@ static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id) *type_p = object->cached.type; return 0; } - + error = odb_read_header_1(&_unused, type_p, db, id, false); if (error == GIT_PASSTHROUGH) { @@ -1175,8 +1205,10 @@ static int read_prefix_1(git_odb_object **out, git_odb *db, } } - if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL) + if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL) { + error = -1; goto out; + } *out = git_cache_store_raw(odb_cache(db), object); @@ -1281,13 +1313,17 @@ int git_odb_write( return error; } -static void hash_header(git_hash_ctx *ctx, git_off_t size, git_otype type) +static int hash_header(git_hash_ctx *ctx, git_off_t size, git_otype type) { char header[64]; - int hdrlen; + size_t hdrlen; + int error; + + if ((error = git_odb__format_object_header(&hdrlen, + header, sizeof(header), size, type)) < 0) + return error; - hdrlen = git_odb__format_object_header(header, sizeof(header), size, type); - git_hash_update(ctx, header, hdrlen); + return git_hash_update(ctx, header, hdrlen); } int git_odb_open_wstream( @@ -1328,12 +1364,11 @@ int git_odb_open_wstream( ctx = git__malloc(sizeof(git_hash_ctx)); GITERR_CHECK_ALLOC(ctx); - if ((error = git_hash_ctx_init(ctx)) < 0) + if ((error = git_hash_ctx_init(ctx)) < 0 || + (error = hash_header(ctx, size, type)) < 0) goto done; - hash_header(ctx, size, type); (*stream)->hash_ctx = ctx; - (*stream)->declared_size = size; (*stream)->received_bytes = 0; |
