Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260805141033.841558-6-matthias.goergens@gmail.com>
Date: Wed,  5 Aug 2026 22:10:28 +0800
From: Matthias Goergens <matthias.goergens@...il.com>
To: musl@...ts.openwall.com
Cc: Matthias Goergens <matthias.goergens@...il.com>
Subject: [PATCH 05/10] regression: test glob GLOB_DOOFFS vector overflow

gl_offs near SIZE_MAX must be rejected with GLOB_NOSPACE without
touching the caller's fields instead of wrapping the result-vector
allocation into out-of-bounds pointer writes.

Covered by the musl patch "regex: avoid overflow sizing glob
result vector".
---
 src/regression/glob-dooffs-overflow.c | 54 +++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 src/regression/glob-dooffs-overflow.c

diff --git a/src/regression/glob-dooffs-overflow.c b/src/regression/glob-dooffs-overflow.c
new file mode 100644
index 0000000..d30e7ba
--- /dev/null
+++ b/src/regression/glob-dooffs-overflow.c
@@ -0,0 +1,54 @@
+// GLOB_DOOFFS makes the caller's gl_offs part of the result-vector
+// size. musl used it in unchecked allocation arithmetic, so gl_offs
+// near SIZE_MAX wrapped the allocation to a small buffer followed by
+// out-of-bounds pointer writes. The oversized vector must be rejected
+// with GLOB_NOSPACE without touching the caller's fields.
+#include <glob.h>
+#include <stdint.h>
+#include <string.h>
+#include "test.h"
+
+int main(void)
+{
+	glob_t g = { .gl_offs = SIZE_MAX };
+	int r;
+
+	r = glob("no-such-file-expected-glob-dooffs-overflow",
+		GLOB_DOOFFS | GLOB_NOCHECK, 0, &g);
+	if (r != GLOB_NOSPACE)
+		t_error("glob with gl_offs == SIZE_MAX returned %d, want GLOB_NOSPACE (%d)\n",
+			r, GLOB_NOSPACE);
+	if (g.gl_pathc != 0 || g.gl_pathv != 0)
+		t_error("failed glob left pathc %zu pathv %p, want 0, NULL\n",
+			g.gl_pathc, (void *)g.gl_pathv);
+	if (g.gl_offs != SIZE_MAX)
+		t_error("failed glob changed gl_offs from %zu to %zu\n",
+			(size_t)SIZE_MAX, g.gl_offs);
+	globfree(&g);
+
+	/* ordinary GLOB_DOOFFS control: reserved slots and the match */
+	g = (glob_t){ .gl_offs = 2 };
+	r = glob("first-no-such-file-expected-glob-dooffs-overflow",
+		GLOB_DOOFFS | GLOB_NOCHECK, 0, &g);
+	if (r != 0 || g.gl_pathc != 1 || !g.gl_pathv ||
+	    g.gl_pathv[0] || g.gl_pathv[1] ||
+	    !g.gl_pathv[2] ||
+	    strcmp(g.gl_pathv[2], "first-no-such-file-expected-glob-dooffs-overflow") ||
+	    g.gl_pathv[3])
+		t_error("ordinary GLOB_DOOFFS glob failed: r %d pathc %zu\n",
+			r, g.gl_pathc);
+
+	/* GLOB_APPEND control: the existing result is extended in place */
+	r = glob("second-no-such-file-expected-glob-dooffs-overflow",
+		GLOB_DOOFFS | GLOB_NOCHECK | GLOB_APPEND, 0, &g);
+	if (r != 0 || g.gl_pathc != 2 || !g.gl_pathv ||
+	    !g.gl_pathv[2] ||
+	    strcmp(g.gl_pathv[2], "first-no-such-file-expected-glob-dooffs-overflow") ||
+	    !g.gl_pathv[3] ||
+	    strcmp(g.gl_pathv[3], "second-no-such-file-expected-glob-dooffs-overflow") ||
+	    g.gl_pathv[4])
+		t_error("GLOB_APPEND glob failed: r %d pathc %zu\n", r, g.gl_pathc);
+	globfree(&g);
+
+	return t_status;
+}
-- 
2.55.0

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.