Patchwork [3,of,8,V3] revlog: catch revlog corruption in index_baserev

login
register
mail settings
Submitter Boris Feld
Date Dec. 28, 2018, 6:12 p.m.
Message ID <a85d334d94953fa99f96.1546020769@pc62.home>
Download mbox | patch
Permalink /patch/37379/
State Accepted
Headers show

Comments

Boris Feld - Dec. 28, 2018, 6:12 p.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1545950077 -3600
#      Thu Dec 27 23:34:37 2018 +0100
# Node ID a85d334d94953fa99f96055baf20f1f0d946b172
# Parent  d313cef8450897c3abf201940f73f57b5dfe8b37
# EXP-Topic sparse-revlog
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r a85d334d9495
revlog: catch revlog corruption in index_baserev

A revision cannot use a base above itself, it can only happens one corrupted
repository.

Ignoring such corrupted could lead to infinite loop.
Yuya Nishihara - Dec. 30, 2018, 8:29 a.m.
On Fri, 28 Dec 2018 19:12:49 +0100, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld <boris.feld@octobus.net>
> # Date 1545950077 -3600
> #      Thu Dec 27 23:34:37 2018 +0100
> # Node ID a85d334d94953fa99f96055baf20f1f0d946b172
> # Parent  d313cef8450897c3abf201940f73f57b5dfe8b37
> # EXP-Topic sparse-revlog
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r a85d334d9495
> revlog: catch revlog corruption in index_baserev

Rebased this onto stable.
Yuya Nishihara - Dec. 30, 2018, 8:46 a.m.
On Fri, 28 Dec 2018 19:12:49 +0100, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld <boris.feld@octobus.net>
> # Date 1545950077 -3600
> #      Thu Dec 27 23:34:37 2018 +0100
> # Node ID a85d334d94953fa99f96055baf20f1f0d946b172
> # Parent  d313cef8450897c3abf201940f73f57b5dfe8b37
> # EXP-Topic sparse-revlog
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r a85d334d9495
> revlog: catch revlog corruption in index_baserev

> +	if (result > rev) {
> +		PyErr_Format(
> +		    PyExc_ValueError,
> +		    "corrupted revlog, revision base above revision: %d, %d",
> +		    rev, result);
> +		return -2;
> +	}

Perhaps, we can catch rev < -1 as well, so index_issnapshotrev() can report
the error properly.

Patch

diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
--- a/mercurial/cext/revlog.c
+++ b/mercurial/cext/revlog.c
@@ -967,6 +967,7 @@  bail:
 static inline int index_baserev(indexObject *self, int rev)
 {
 	const char *data;
+	int result;
 
 	if (rev >= self->length) {
 		PyObject *tuple =
@@ -975,15 +976,23 @@  static inline int index_baserev(indexObj
 		if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 3), &ret)) {
 			return -2;
 		}
-		return (int)ret;
+		result = (int)ret;
 	} else {
 		data = index_deref(self, rev);
 		if (data == NULL) {
 			return -2;
 		}
 
-		return getbe32(data + 16);
+		result = getbe32(data + 16);
 	}
+	if (result > rev) {
+		PyErr_Format(
+		    PyExc_ValueError,
+		    "corrupted revlog, revision base above revision: %d, %d",
+		    rev, result);
+		return -2;
+	}
+	return result;
 }
 
 static PyObject *index_deltachain(indexObject *self, PyObject *args)