diff mercurial/cext/revlog.c @ 33475:f501322512b6

parsers: fix invariant bug in find_deepest (issue5623) find_deepest is used to find the "best" ancestors given a list. In the main loop it keeps an invariant called 'ninteresting' which is supposed to contain the number of non-zero entries in the 'interesting' array. This invariant is incorrectly maintained, however, which leads the the algorithm returning an empty result for certain graphs. This has been fixed. Also, the 'interesting' array is supposed to fit 2^ancestors values, but is incorrectly allocated to twice that size. This has been fixed as well. The tests in test-ancestor.py compare the Python and C versions of the code, and report the error correctly, since the Python version works correct. Even so, I have added an additional test against the expected result, in the event that both algorithms have an identical error in the future. This fixes issue5623.
author Sune Foldager <cryo@cyanite.org>
date Fri, 14 Jul 2017 13:48:17 +0200
parents f4f52bb362e6
children 0f4ac3b6dee4
line wrap: on
line diff
--- a/mercurial/cext/revlog.c	Fri Jun 30 03:45:57 2017 +0200
+++ b/mercurial/cext/revlog.c	Fri Jul 14 13:48:17 2017 +0200
@@ -1464,7 +1464,7 @@
 		goto bail;
 	}
 
-	interesting = calloc(sizeof(*interesting), 2 << revcount);
+	interesting = calloc(sizeof(*interesting), 1 << revcount);
 	if (interesting == NULL) {
 		PyErr_NoMemory();
 		goto bail;
@@ -1481,6 +1481,8 @@
 		interesting[b] = 1;
 	}
 
+	/* invariant: ninteresting is the number of non-zero entries in
+	 * interesting. */
 	ninteresting = (int)revcount;
 
 	for (v = maxrev; v >= 0 && ninteresting > 1; v--) {
@@ -1523,8 +1525,10 @@
 					continue;
 				seen[p] = nsp;
 				interesting[sp] -= 1;
-				if (interesting[sp] == 0 && interesting[nsp] > 0)
+				if (interesting[sp] == 0)
 					ninteresting -= 1;
+				if (interesting[nsp] == 0)
+					ninteresting += 1;
 				interesting[nsp] += 1;
 			}
 		}