changeset 39422:adacefb0b7ea stable

dirstate: use tuple interface to fix leak in pack_dirstate() Spotted by ASAN. Unlike PyTuple_GET_ITEM(), PySequence_ITEM() returns a new reference. This bug could be fixed by inserting Py_CLEAR() and Py_XDECREF() appropriately, but I think requiring a tuple object is simpler and less error-prone. The cext version is jumped to 10 since 6..9 are used in the default branch. We'll need to bump it again at merge.
author Yuya Nishihara <yuya@tcha.org>
date Wed, 05 Sep 2018 20:52:22 +0900
parents ad76032d27da
children ca77788c81bc
files mercurial/cext/parsers.c mercurial/dirstate.py mercurial/policy.py
diffstat 3 files changed, 10 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cext/parsers.c	Wed Sep 05 22:10:41 2018 +0900
+++ b/mercurial/cext/parsers.c	Wed Sep 05 20:52:22 2018 +0900
@@ -382,12 +382,12 @@
 	char *p, *s;
 	int now;
 
-	if (!PyArg_ParseTuple(args, "O!O!Oi:pack_dirstate", &PyDict_Type, &map,
-	                      &PyDict_Type, &copymap, &pl, &now))
+	if (!PyArg_ParseTuple(args, "O!O!O!i:pack_dirstate", &PyDict_Type, &map,
+	                      &PyDict_Type, &copymap, &PyTuple_Type, &pl, &now))
 		return NULL;
 
-	if (!PySequence_Check(pl) || PySequence_Size(pl) != 2) {
-		PyErr_SetString(PyExc_TypeError, "expected 2-element sequence");
+	if (PyTuple_Size(pl) != 2) {
+		PyErr_SetString(PyExc_TypeError, "expected 2-element tuple");
 		return NULL;
 	}
 
@@ -416,14 +416,14 @@
 
 	p = PyBytes_AS_STRING(packobj);
 
-	pn = PySequence_ITEM(pl, 0);
+	pn = PyTuple_GET_ITEM(pl, 0);
 	if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
 		PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
 		goto bail;
 	}
 	memcpy(p, s, l);
 	p += 20;
-	pn = PySequence_ITEM(pl, 1);
+	pn = PyTuple_GET_ITEM(pl, 1);
 	if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
 		PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
 		goto bail;
@@ -713,7 +713,7 @@
 void manifest_module_init(PyObject *mod);
 void revlog_module_init(PyObject *mod);
 
-static const int version = 5;
+static const int version = 10;
 
 static void module_init(PyObject *mod)
 {
--- a/mercurial/dirstate.py	Wed Sep 05 22:10:41 2018 +0900
+++ b/mercurial/dirstate.py	Wed Sep 05 20:52:22 2018 +0900
@@ -1392,9 +1392,9 @@
 
             l = len(st)
             if l == 40:
-                self._parents = st[:20], st[20:40]
+                self._parents = (st[:20], st[20:40])
             elif l == 0:
-                self._parents = [nullid, nullid]
+                self._parents = (nullid, nullid)
             else:
                 raise error.Abort(_('working directory state appears '
                                     'damaged!'))
--- a/mercurial/policy.py	Wed Sep 05 22:10:41 2018 +0900
+++ b/mercurial/policy.py	Wed Sep 05 20:52:22 2018 +0900
@@ -69,7 +69,7 @@
     (r'cext', r'bdiff'): 3,
     (r'cext', r'mpatch'): 1,
     (r'cext', r'osutil'): 4,
-    (r'cext', r'parsers'): 5,
+    (r'cext', r'parsers'): 10,
 }
 
 # map import request to other package or module