Commit 8da93944f3d3c271ea7a2ec035c6ea48654fa71e

Patrick Steinhardt 2018-12-01T10:52:44

idxmap: have `resize` functions return proper error code The currently existing function `git_idxmap_resize` and `git_idxmap_icase_resize` do not return any error codes at all due to their previous implementation making use of a macro. Due to that, it is impossible to see whether the resize operation might have failed due to an out-of-memory situation. Fix this by providing a proper error code. Adjust callers to make use of it.

diff --git a/src/idxmap.c b/src/idxmap.c
index 3511229..e3fcfb8 100644
--- a/src/idxmap.c
+++ b/src/idxmap.c
@@ -68,6 +68,24 @@ void git_idxmap_icase_clear(git_idxmap_icase *map)
 	kh_clear(idxicase, map);
 }
 
+int git_idxmap_resize(git_idxmap *map, size_t size)
+{
+	if (kh_resize(idx, map, size) < 0) {
+		git_error_set_oom();
+		return -1;
+	}
+	return 0;
+}
+
+int git_idxmap_icase_resize(git_idxmap_icase *map, size_t size)
+{
+	if (kh_resize(idxicase, map, size) < 0) {
+		git_error_set_oom();
+		return -1;
+	}
+	return 0;
+}
+
 void *git_idxmap_get(git_idxmap *map, const git_index_entry *key)
 {
 	size_t idx = git_idxmap_lookup_index(map, key);
@@ -177,16 +195,6 @@ int git_idxmap_icase_has_data(git_idxmap_icase *map, size_t idx)
 	return kh_exist(map, idx);
 }
 
-void git_idxmap_resize(git_idxmap *map, size_t size)
-{
-	kh_resize(idx, map, size);
-}
-
-void git_idxmap_icase_resize(git_idxmap_icase *map, size_t size)
-{
-	kh_resize(idxicase, map, size);
-}
-
 void git_idxmap_delete_at(git_idxmap *map, size_t idx)
 {
 	kh_del(idx, map, idx);
diff --git a/src/idxmap.h b/src/idxmap.h
index 55d60d5..cf14254 100644
--- a/src/idxmap.h
+++ b/src/idxmap.h
@@ -77,6 +77,26 @@ void git_idxmap_clear(git_idxmap *map);
 void git_idxmap_icase_clear(git_idxmap_icase *map);
 
 /**
+ * Resize the map by allocating more memory.
+ *
+ * @param map map that shall be resized
+ * @param size count of entries that the map shall hold
+ * @return `0` if the map was successfully resized, a negative
+ *         error code otherwise
+ */
+int git_idxmap_resize(git_idxmap *map, size_t size);
+
+/**
+ * Resize the map by allocating more memory.
+ *
+ * @param map map that shall be resized
+ * @param size count of entries that the map shall hold
+ * @return `0` if the map was successfully resized, a negative
+ *         error code otherwise
+ */
+int git_idxmap_icase_resize(git_idxmap_icase *map, size_t size);
+
+/**
  * Return value associated with the given key.
  *
  * @param map map to search key in
@@ -137,9 +157,6 @@ int git_idxmap_icase_valid_index(git_idxmap_icase *map, size_t idx);
 int git_idxmap_has_data(git_idxmap *map, size_t idx);
 int git_idxmap_icase_has_data(git_idxmap_icase *map, size_t idx);
 
-void git_idxmap_resize(git_idxmap *map, size_t size);
-void git_idxmap_icase_resize(git_idxmap_icase *map, size_t size);
-
 void git_idxmap_delete_at(git_idxmap *map, size_t idx);
 void git_idxmap_icase_delete_at(git_idxmap_icase *map, size_t idx);
 
diff --git a/src/index.c b/src/index.c
index 308b89a..ee8dfd5 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1619,8 +1619,9 @@ int git_index__fill(git_index *index, const git_vector *source_entries)
 	if (!source_entries->length)
 		return 0;
 
-	git_vector_size_hint(&index->entries, source_entries->length);
-	git_idxmap_resize(index->entries_map, (size_t)(source_entries->length * 1.3));
+	if (git_vector_size_hint(&index->entries, source_entries->length) < 0 ||
+	    git_idxmap_resize(index->entries_map, (size_t)(source_entries->length * 1.3)) < 0)
+		return -1;
 
 	git_vector_foreach(source_entries, i, source_entry) {
 		git_index_entry *entry = NULL;
@@ -2608,10 +2609,12 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
 
 	assert(!index->entries.length);
 
-	if (index->ignore_case)
-		git_idxmap_icase_resize((git_idxmap_icase *) index->entries_map, header.entry_count);
-	else
-		git_idxmap_resize(index->entries_map, header.entry_count);
+	if (index->ignore_case &&
+	    (error = git_idxmap_icase_resize((git_idxmap_icase *) index->entries_map,
+					     header.entry_count)) < 0)
+		return error;
+	else if ((error = git_idxmap_resize(index->entries_map, header.entry_count)) < 0)
+		return error;
 
 	/* Parse all the entries */
 	for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
@@ -3125,10 +3128,12 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
 	if ((error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data)) < 0)
 		goto cleanup;
 
-	if (index->ignore_case)
-		git_idxmap_icase_resize((git_idxmap_icase *) entries_map, entries.length);
-	else
-		git_idxmap_resize(entries_map, entries.length);
+	if (index->ignore_case &&
+	    (error = git_idxmap_icase_resize((git_idxmap_icase *) entries_map,
+					     entries.length)) < 0)
+		goto cleanup;
+	else if ((error = git_idxmap_resize(entries_map, entries.length)) < 0)
+		goto cleanup;
 
 	git_vector_foreach(&entries, i, e) {
 		INSERT_IN_MAP_EX(index, entries_map, e, error);
@@ -3185,10 +3190,13 @@ static int git_index_read_iterator(
 	    (error = git_idxmap_new(&new_entries_map)) < 0)
 		goto done;
 
-	if (index->ignore_case && new_length_hint)
-		git_idxmap_icase_resize((git_idxmap_icase *) new_entries_map, new_length_hint);
-	else if (new_length_hint)
-		git_idxmap_resize(new_entries_map, new_length_hint);
+	if (index->ignore_case && new_length_hint &&
+	    (error = git_idxmap_icase_resize((git_idxmap_icase *) new_entries_map,
+					     new_length_hint)) < 0)
+		goto done;
+	else if (new_length_hint &&
+	         (error = git_idxmap_resize(new_entries_map, new_length_hint)) < 0)
+		goto done;
 
 	opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE |
 		GIT_ITERATOR_INCLUDE_CONFLICTS;