]> git.proxmox.com Git - libgit2.git/commitdiff
odb: improve error handling in read_prefix_1
authorPatrick Steinhardt <ps@pks.im>
Fri, 28 Apr 2017 12:03:54 +0000 (14:03 +0200)
committerPatrick Steinhardt <ps@pks.im>
Fri, 28 Apr 2017 12:10:37 +0000 (14:10 +0200)
The read_prefix_1 function has several return statements springled
throughout the code. As we have to free memory upon getting an error,
the free code has to be repeated at every single retrun -- which it is
not, so we have a memory leak here.

Refactor the code to use the typical `goto out` pattern, which will free
data when an error has occurred. While we're at it, we can also improve
the error message thrown when multiple ambiguous prefixes are found. It
will now include the colliding prefixes.

src/odb.c

index 157a3808e48c43250f5dabcc54defaf54b499c47..e87114769170a7e3b41a10845d4f79957fb6e4bf 100644 (file)
--- a/src/odb.c
+++ b/src/odb.c
@@ -1099,9 +1099,9 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
                const git_oid *key, size_t len, bool only_refreshed)
 {
        size_t i;
-       int error = GIT_ENOTFOUND;
+       int error;
        git_oid found_full_oid = {{0}};
-       git_rawobj raw;
+       git_rawobj raw = {0};
        void *data = NULL;
        bool found = false;
        git_odb_object *object;
@@ -1120,14 +1120,22 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
                                continue;
 
                        if (error)
-                               return error;
+                               goto out;
 
                        git__free(data);
                        data = raw.data;
 
                        if (found && git_oid__cmp(&full_oid, &found_full_oid)) {
-                               git__free(raw.data);
-                               return git_odb__error_ambiguous("multiple matches for prefix");
+                               git_buf buf = GIT_BUF_INIT;
+
+                               git_buf_printf(&buf, "multiple matches for prefix: %s",
+                                       git_oid_tostr_s(&full_oid));
+                               git_buf_printf(&buf, " %s",
+                                       git_oid_tostr_s(&found_full_oid));
+
+                               error = git_odb__error_ambiguous(buf.ptr);
+                               git_buf_free(&buf);
+                               goto out;
                        }
 
                        found_full_oid = full_oid;
@@ -1139,10 +1147,15 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
                return GIT_ENOTFOUND;
 
        if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL)
-               return -1;
+               goto out;
 
        *out = git_cache_store_raw(odb_cache(db), object);
-       return 0;
+
+out:
+       if (error)
+               git__free(raw.data);
+
+       return error;
 }
 
 int git_odb_read_prefix(