Commit ca901e7b0fb38a7f4748ff5fcde7a2779f3a7771

Ben Straub 2012-11-29T15:16:19

Deploy GIT_DIFF_FIND_OPTIONS_INIT

diff --git a/src/diff_tform.c b/src/diff_tform.c
index 987d4b8..1df0410 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -168,6 +168,18 @@ int git_diff_merge(
 	return error;
 }
 
+static bool find_opts_has_valid_version(const git_diff_find_options *opts)
+{
+	if (!opts)
+		return true;
+
+	if (opts->version > 0 && opts->version <= GIT_DIFF_FIND_OPTIONS_VERSION)
+		return true;
+
+	giterr_set(GITERR_INVALID, "Invalid version %d on git_diff_find_options", opts->version);
+	return false;
+}
+
 #define DEFAULT_THRESHOLD 50
 #define DEFAULT_BREAK_REWRITE_THRESHOLD 60
 #define DEFAULT_TARGET_LIMIT 200
@@ -187,7 +199,8 @@ static int normalize_find_opts(
 	if (given != NULL)
 		memcpy(opts, given, sizeof(*opts));
 	else {
-		memset(opts, 0, sizeof(*opts));
+		git_diff_find_options init = GIT_DIFF_FIND_OPTIONS_INIT;
+		memmove(opts, &init, sizeof(init));
 
 		opts->flags = GIT_DIFF_FIND_RENAMES;
 
@@ -198,6 +211,9 @@ static int normalize_find_opts(
 			opts->flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES;
 	}
 
+	if (!find_opts_has_valid_version(opts))
+		return -1;
+
 	/* some flags imply others */
 
 	if (opts->flags & GIT_DIFF_FIND_RENAMES_FROM_REWRITES)
diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c
index 18b7f77..2995b4e 100644
--- a/tests-clar/diff/rename.c
+++ b/tests-clar/diff/rename.c
@@ -34,7 +34,7 @@ void test_diff_rename__match_oid(void)
 	git_tree *old_tree, *new_tree;
 	git_diff_list *diff;
 	git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
-	git_diff_find_options opts;
+	git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
 	diff_expects exp;
 
 	old_tree = resolve_commit_oid_to_tree(g_repo, old_sha);
@@ -84,7 +84,6 @@ void test_diff_rename__match_oid(void)
 	 *          31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \
 	 *          2bc7f351d20b53f1c72c16c4b036e491c478c49a
 	 */
-	memset(&opts, 0, sizeof(opts));
 	opts.flags = GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED;
 	cl_git_pass(git_diff_find_similar(diff, &opts));
 
@@ -102,3 +101,35 @@ void test_diff_rename__match_oid(void)
 	git_tree_free(old_tree);
 	git_tree_free(new_tree);
 }
+
+void test_diff_rename__checks_options_version(void)
+{
+	const char *old_sha = "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2";
+	const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a";
+	git_tree *old_tree, *new_tree;
+	git_diff_list *diff;
+	git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
+	git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
+	const git_error *err;
+
+	old_tree = resolve_commit_oid_to_tree(g_repo, old_sha);
+	new_tree = resolve_commit_oid_to_tree(g_repo, new_sha);
+	diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED;
+	cl_git_pass(git_diff_tree_to_tree(
+		&diff, g_repo, old_tree, new_tree, &diffopts));
+
+	opts.version = 0;
+	cl_git_fail(git_diff_find_similar(diff, &opts));
+	err = giterr_last();
+	cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+	giterr_clear();
+	opts.version = 1024;
+	cl_git_fail(git_diff_find_similar(diff, &opts));
+	err = giterr_last();
+	cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+	git_diff_list_free(diff);
+	git_tree_free(old_tree);
+	git_tree_free(new_tree);
+}