Patchwork [2,of,3,STABLE] rust: fix possible out-of-bounds read through index_get_parents()

login
register
mail settings
Submitter Yuya Nishihara
Date Oct. 28, 2018, 1:11 p.m.
Message ID <28a5ec244ba88ce4a46a.1540732262@mimosa>
Download mbox | patch
Permalink /patch/36282/
State Superseded
Headers show

Comments

Yuya Nishihara - Oct. 28, 2018, 1:11 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1540729744 -32400
#      Sun Oct 28 21:29:04 2018 +0900
# Branch stable
# Node ID 28a5ec244ba88ce4a46a26a32c24fa36f7597245
# Parent  2af0076a5465be08dc2dc91e352abfbbe9c2ab17
rust: fix possible out-of-bounds read through index_get_parents()

index_get_parents() is an internal function, which doesn't check if the
specified rev is valid. If rustlazyancestors() were instantiated with an
invalid stoprev, it would access to invalid memory region.

Patch

diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
--- a/mercurial/cext/revlog.c
+++ b/mercurial/cext/revlog.c
@@ -2308,7 +2308,7 @@  struct rustlazyancestorsObjectStruct {
 /* FFI exposed from Rust code */
 rustlazyancestorsObject *rustlazyancestors_init(
 	indexObject *index,
-	/* to pass index_get_parents() */
+	/* to pass index_get_parents_checked() */
 	int (*)(indexObject *, Py_ssize_t, int*, int),
 	/* intrevs vector */
 	Py_ssize_t initrevslen, long *initrevs,
@@ -2318,6 +2318,16 @@  void rustlazyancestors_drop(rustlazyance
 int rustlazyancestors_next(rustlazyancestorsObject *self);
 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev);
 
+static int index_get_parents_checked(indexObject *self, Py_ssize_t rev,
+                                     int *ps, int maxrev)
+{
+	if (rev < 0 || rev >= index_length(self)) {
+		PyErr_SetString(PyExc_ValueError, "rev out of range");
+		return -1;
+	}
+	return index_get_parents(self, rev, ps, maxrev);
+}
+
 /* CPython instance methods */
 static int rustla_init(rustlazyancestorsObject *self,
                        PyObject *args) {
@@ -2358,12 +2368,13 @@  static int rustla_init(rustlazyancestors
 		goto bail;
 
 	self->iter = rustlazyancestors_init(index,
-		                            index_get_parents,
+		                            index_get_parents_checked,
 		                            linit, initrevs,
 		                            stoprev, inclusive);
 	if (self->iter == NULL) {
 		/* if this is because of GraphError::ParentOutOfRange
-		 * index_get_parents() has already set the proper ValueError */
+		 * index_get_parents_checked() has already set the proper
+		 * ValueError */
 		goto bail;
 	}