Commit 8564a0224abe09beaacb2d2e7a54b16f8fcea7d1

Russell Belfer 2013-04-29T08:51:24

Fix fragile git_oid_ncmp git_oid_ncmp was making some assumptions about the length of the data - this shifts the check to the top of the loop so it will work more robustly, limits the max, and adds some tests to verify the functionality.

diff --git a/src/oid.c b/src/oid.c
index 59c1546..4b66990 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -176,13 +176,16 @@ int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, size_t len)
 	const unsigned char *a = oid_a->id;
 	const unsigned char *b = oid_b->id;
 
-	do {
+	if (len > GIT_OID_HEXSZ)
+		len = GIT_OID_HEXSZ;
+
+	while (len > 1) {
 		if (*a != *b)
 			return 1;
 		a++;
 		b++;
 		len -= 2;
-	} while (len > 1);
+	};
 
 	if (len)
 		if ((*a ^ *b) & 0xf0)
diff --git a/tests-clar/core/oid.c b/tests-clar/core/oid.c
index 08791cc..d863a3e 100644
--- a/tests-clar/core/oid.c
+++ b/tests-clar/core/oid.c
@@ -27,4 +27,22 @@ void test_core_oid__streq(void)
 
 	cl_assert(git_oid_streq(&idp, "deadbeef") == -1);
 	cl_assert(git_oid_streq(&idp, "I'm not an oid.... :)") == -1);
+
+void test_core_oid__ncmp(void)
+{
+	cl_assert(!git_oid_ncmp(&id, &idp, 0));
+	cl_assert(!git_oid_ncmp(&id, &idp, 1));
+	cl_assert(!git_oid_ncmp(&id, &idp, 2));
+	cl_assert(!git_oid_ncmp(&id, &idp, 17));
+	cl_assert(!git_oid_ncmp(&id, &idp, 18));
+	cl_assert(git_oid_ncmp(&id, &idp, 19));
+	cl_assert(git_oid_ncmp(&id, &idp, 40));
+	cl_assert(git_oid_ncmp(&id, &idp, 41));
+	cl_assert(git_oid_ncmp(&id, &idp, 42));
+
+	cl_assert(!git_oid_ncmp(&id, &id, 0));
+	cl_assert(!git_oid_ncmp(&id, &id, 1));
+	cl_assert(!git_oid_ncmp(&id, &id, 39));
+	cl_assert(!git_oid_ncmp(&id, &id, 40));
+	cl_assert(!git_oid_ncmp(&id, &id, 41));
 }