Patchwork D7411: dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies

login
register
mail settings
Submitter phabricator
Date Nov. 15, 2019, 4:07 a.m.
Message ID <ec24b161f0cd9cd43267700a61994562@localhost.localdomain>
Download mbox | patch
Permalink /patch/43257/
State Not Applicable
Headers show

Comments

phabricator - Nov. 15, 2019, 4:07 a.m.
Closed by commit rHG0796e266d26b: dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies (authored by durin42).
durin42 marked an inline comment as done.
This revision was automatically updated to reflect the committed changes.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7411?vs=18112&id=18143

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7411/new/

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

AFFECTED FILES
  mercurial/cext/dirs.c

CHANGE DETAILS




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

Patch

diff --git a/mercurial/cext/dirs.c b/mercurial/cext/dirs.c
--- a/mercurial/cext/dirs.c
+++ b/mercurial/cext/dirs.c
@@ -9,6 +9,7 @@ 
 
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
+#include <string.h>
 
 #include "util.h"
 
@@ -48,12 +49,19 @@ 
 	return pos;
 }
 
+/* Mercurial will fail to run on directory hierarchies deeper than
+ * this constant, so we should try and keep this constant as big as
+ * possible.
+ */
+#define MAX_DIRS_DEPTH 2048
+
 static int _addpath(PyObject *dirs, PyObject *path)
 {
 	const char *cpath = PyBytes_AS_STRING(path);
 	Py_ssize_t pos = PyBytes_GET_SIZE(path);
 	PyObject *key = NULL;
 	int ret = -1;
+	size_t num_slashes = 0;
 
 	/* This loop is super critical for performance. That's why we inline
 	 * access to Python structs instead of going through a supported API.
@@ -65,6 +73,12 @@ 
 	 * unnoticed. */
 	while ((pos = _finddir(cpath, pos - 1)) != -1) {
 		PyObject *val;
+		++num_slashes;
+		if (num_slashes > MAX_DIRS_DEPTH) {
+			PyErr_SetString(PyExc_ValueError,
+			                "Directory hierarchy too deep.");
+			goto bail;
+		}
 
 		/* Sniff for trailing slashes, a marker of an invalid input. */
 		if (pos > 0 && cpath[pos - 1] == '/') {