Patchwork D2587: cext: accept arguments as Py_buffer

login
register
mail settings
Submitter phabricator
Date March 3, 2018, 8:16 p.m.
Message ID <cf5c3fb9af70eaa82a54fe3c9358e4c1@localhost.localdomain>
Download mbox | patch
Permalink /patch/28828/
State Not Applicable
Headers show

Comments

phabricator - March 3, 2018, 8:16 p.m.
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG68026dd7c4f9: cext: accept arguments as Py_buffer (authored by indygreg, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D2587?vs=6436&id=6466#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2587?vs=6436&id=6466

REVISION DETAIL
  https://phab.mercurial-scm.org/D2587

AFFECTED FILES
  mercurial/cext/bdiff.c
  mercurial/mdiff.py

CHANGE DETAILS




To: indygreg, #hg-reviewers, yuja
Cc: mercurial-devel

Patch

diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py
--- a/mercurial/mdiff.py
+++ b/mercurial/mdiff.py
@@ -30,17 +30,9 @@ 
 fixws = bdiff.fixws
 patches = mpatch.patches
 patchedsize = mpatch.patchedsize
-_textdiff = bdiff.bdiff
+textdiff = bdiff.bdiff
 splitnewlines = bdiff.splitnewlines
 
-# On Python 3, util.buffer() creates a memoryview, which appears not
-# supporting the buffer protocol
-if pycompat.ispy3:
-    def textdiff(a, b):
-        return _textdiff(bytes(a), bytes(b))
-else:
-    textdiff = _textdiff
-
 class diffopts(object):
     '''context is the number of context lines
     text treats all files as text
diff --git a/mercurial/cext/bdiff.c b/mercurial/cext/bdiff.c
--- a/mercurial/cext/bdiff.c
+++ b/mercurial/cext/bdiff.c
@@ -60,7 +60,8 @@ 
 
 static PyObject *bdiff(PyObject *self, PyObject *args)
 {
-	char *sa, *sb, *rb, *ia, *ib;
+	Py_buffer ba, bb;
+	char *rb, *ia, *ib;
 	PyObject *result = NULL;
 	struct bdiff_line *al = NULL, *bl = NULL;
 	struct bdiff_hunk l, *h;
@@ -70,25 +71,39 @@ 
 
 	l.next = NULL;
 
-	if (!PyArg_ParseTuple(args, PY23("s#s#:bdiff", "y#y#:bdiff"), &sa, &la,
-	                      &sb, &lb))
+	if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba, &bb))
 		return NULL;
 
+	if (!PyBuffer_IsContiguous(&ba, 'C') || ba.ndim > 1) {
+		PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous");
+		goto cleanup;
+	}
+
+	if (!PyBuffer_IsContiguous(&bb, 'C') || bb.ndim > 1) {
+		PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous");
+		goto cleanup;
+	}
+
+	la = ba.len;
+	lb = bb.len;
+
 	if (la > UINT_MAX || lb > UINT_MAX) {
 		PyErr_SetString(PyExc_ValueError, "bdiff inputs too large");
-		return NULL;
+		goto cleanup;
 	}
 
 	_save = PyEval_SaveThread();
 
 	lmax = la > lb ? lb : la;
-	for (ia = sa, ib = sb; li < lmax && *ia == *ib; ++li, ++ia, ++ib)
+	for (ia = ba.buf, ib = bb.buf; li < lmax && *ia == *ib;
+	     ++li, ++ia, ++ib) {
 		if (*ia == '\n')
 			lcommon = li + 1;
+	}
 	/* we can almost add: if (li == lmax) lcommon = li; */
 
-	an = bdiff_splitlines(sa + lcommon, la - lcommon, &al);
-	bn = bdiff_splitlines(sb + lcommon, lb - lcommon, &bl);
+	an = bdiff_splitlines(ba.buf + lcommon, la - lcommon, &al);
+	bn = bdiff_splitlines(bb.buf + lcommon, lb - lcommon, &bl);
 	if (!al || !bl) {
 		PyErr_NoMemory();
 		goto cleanup;
@@ -137,6 +152,8 @@ 
 cleanup:
 	if (_save)
 		PyEval_RestoreThread(_save);
+	PyBuffer_Release(&ba);
+	PyBuffer_Release(&bb);
 	if (al) {
 		free(al);
 	}