diff --git a/mercurial/mpatch.c b/mercurial/mpatch.c --- a/mercurial/mpatch.c +++ b/mercurial/mpatch.c @@ -404,7 +404,8 @@ PyMODINIT_FUNC PyInit_mpatch(void) if (m == NULL) return NULL; - mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL); + mpatch_Error = PyErr_NewException("mercurial.mpatch.mpatchError", + NULL, NULL); Py_INCREF(mpatch_Error); PyModule_AddObject(m, "mpatchError", mpatch_Error); @@ -415,6 +416,7 @@ PyMODINIT_FUNC initmpatch(void) { Py_InitModule3("mpatch", methods, mpatch_doc); - mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL); + mpatch_Error = PyErr_NewException("mercurial.mpatch.mpatchError", + NULL, NULL); } #endif diff --git a/mercurial/pure/mpatch.py b/mercurial/pure/mpatch.py --- a/mercurial/pure/mpatch.py +++ b/mercurial/pure/mpatch.py @@ -12,6 +12,10 @@ import struct StringIO = cStringIO.StringIO +class mpatchError(Exception): + """error raised when a delta cannot be decoded + """ + # This attempts to apply a series of patches in time proportional to # the total size of the patches, rather than patches * len(text). This # means rather than shuffling strings around, we shuffle around @@ -84,7 +88,10 @@ def patches(a, bins): last = 0 while pos < end: m.seek(pos) - p1, p2, l = struct.unpack(">lll", m.read(12)) + try: + p1, p2, l = struct.unpack(">lll", m.read(12)) + except struct.error: + raise mpatchError("patch cannot be decoded") _pull(new, frags, p1 - last) # what didn't change _pull([], frags, p2 - p1) # what got deleted new.append((l, pos + 12)) # what got added @@ -114,7 +121,7 @@ def patchedsize(orig, delta): outlen += length if bin != binend: - raise ValueError("patch cannot be decoded") + raise mpatchError("patch cannot be decoded") outlen += orig - last return outlen diff --git a/tests/test-revlog.t b/tests/test-revlog.t --- a/tests/test-revlog.t +++ b/tests/test-revlog.t @@ -11,5 +11,5 @@ Test for CVE-2016-3630 rev offset length delta linkrev nodeid p1 p2 0 0 19 -1 2 99e0332bd498 000000000000 000000000000 1 19 12 0 3 6674f57a23d8 99e0332bd498 000000000000 - $ hg debugdata a.i 1 2>&1 | grep decoded - mpatch.mpatchError: patch cannot be decoded + $ hg debugdata a.i 1 2>&1 | egrep 'Error:.*decoded' + mercurial.mpatch.mpatchError: patch cannot be decoded