85 lines
2.7 KiB
Diff
85 lines
2.7 KiB
Diff
# HG changeset patch
|
|
# User Augie Fackler <augie@google.com>
|
|
# Date 1571354962 14400
|
|
# Node ID 5d40317d42b7083b49467502549e25f144888cb3
|
|
# Parent 3a463e5e470b40c275091a38b1a4464e36c0c5a4
|
|
dirs: reject consecutive slashes in paths
|
|
|
|
We shouldn't ever see those, and the fuzzer go really excited that if
|
|
it gives us a 65k string with 55k slashes in it we use a lot of RAM.
|
|
|
|
This is a better fix than what I tried in D7105. It was suggested by
|
|
Yuya, and I verified it does in fact cause the fuzzer to not OOM.
|
|
|
|
This is a revision of D7234, but with the missing set of an error
|
|
added. I added a unit test of the dirs behavior because I needed to
|
|
reason more carefully about the failure modes around consecutive
|
|
slashes.
|
|
|
|
Differential Revision: https://phab.mercurial-scm.org/D7252
|
|
|
|
diff -r 3a463e5e470b -r 5d40317d42b7 mercurial/cext/dirs.c
|
|
--- a/mercurial/cext/dirs.c Tue Nov 05 22:56:12 2019 -0500
|
|
+++ b/mercurial/cext/dirs.c Thu Oct 17 19:29:22 2019 -0400
|
|
@@ -66,6 +66,14 @@
|
|
while ((pos = _finddir(cpath, pos - 1)) != -1) {
|
|
PyObject *val;
|
|
|
|
+ /* Sniff for trailing slashes, a marker of an invalid input. */
|
|
+ if (pos > 0 && cpath[pos - 1] == '/') {
|
|
+ PyErr_SetString(
|
|
+ PyExc_ValueError,
|
|
+ "found invalid consecutive slashes in path");
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
key = PyBytes_FromStringAndSize(cpath, pos);
|
|
if (key == NULL)
|
|
goto bail;
|
|
diff -r 3a463e5e470b -r 5d40317d42b7 mercurial/util.py
|
|
--- a/mercurial/util.py Tue Nov 05 22:56:12 2019 -0500
|
|
+++ b/mercurial/util.py Thu Oct 17 19:29:22 2019 -0400
|
|
@@ -3515,6 +3515,10 @@
|
|
def addpath(self, path):
|
|
dirs = self._dirs
|
|
for base in finddirs(path):
|
|
+ if base.endswith(b'/'):
|
|
+ raise ValueError(
|
|
+ "found invalid consecutive slashes in path: %r" % base
|
|
+ )
|
|
if base in dirs:
|
|
dirs[base] += 1
|
|
return
|
|
diff -r 3a463e5e470b -r 5d40317d42b7 tests/test-dirs.py
|
|
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
|
|
+++ b/tests/test-dirs.py Thu Oct 17 19:29:22 2019 -0400
|
|
@@ -0,0 +1,27 @@
|
|
+from __future__ import absolute_import
|
|
+
|
|
+import unittest
|
|
+
|
|
+import silenttestrunner
|
|
+
|
|
+from mercurial import util
|
|
+
|
|
+
|
|
+class dirstests(unittest.TestCase):
|
|
+ def testdirs(self):
|
|
+ for case, want in [
|
|
+ (b'a/a/a', [b'a', b'a/a', b'']),
|
|
+ (b'alpha/beta/gamma', [b'', b'alpha', b'alpha/beta']),
|
|
+ ]:
|
|
+ d = util.dirs({})
|
|
+ d.addpath(case)
|
|
+ self.assertEqual(sorted(d), sorted(want))
|
|
+
|
|
+ def testinvalid(self):
|
|
+ with self.assertRaises(ValueError):
|
|
+ d = util.dirs({})
|
|
+ d.addpath(b'a//b')
|
|
+
|
|
+
|
|
+if __name__ == '__main__':
|
|
+ silenttestrunner.main(__name__)
|
|
|