git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] path.c: add_to_trie - possible global-buffer-overflow fixed

From
Rubén Justo <rjusto@gmail.com>
Date
Oct 17, 2022, 06:12 UTC
Message-ID
<d28ecc16-1e73-98bb-04e7-33f4f8986986@gmail.com>

Since 4e09cf2ac (path: optimize common dir checking, 2015-08-31) a trie is used to search over the common_list array. The trie is formed from a well-known list of values. With the current implementation there can be problems if the current values are rearranged or new values are introduced.

This is fine:
	static const struct common_dir common_list[] = {
		{ 1, 1, 1, "logs" },
		{ 1, 0, 0, "logs/HEAD" },
		...
But this will lead to a global-buffer-overflow:
	static const struct common_dir common_list[] = {
		{ 1, 0, 0, "logs/HEAD" },
		{ 1, 1, 1, "logs" },
		...
And this will confuse and is probably a bug:
	static const struct common_dir common_list[] = {
		{ 1, 1, 1, "logs" },
		{ 0, 0, 0, "logs" },
		...
Let's fix the former and throw an assert on the latter.
Signed-off-by: Rubén Justo <rjusto@gmail.com>
---
 path.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/path.c b/path.c
index a3cfcd8a6e..a925cf073b 100644
--- a/path.c
+++ b/path.c
@@ -185,13 +185,6 @@ static void *add_to_trie(struct trie *root, const char *key, void *value)
 	void *old;
 	int i;
 
-	if (!*key) {
-		/* we have reached the end of the key */
-		old = root->value;
-		root->value = value;
-		return old;
-	}
-
 	for (i = 0; i < root->len; i++) {
 		if (root->contents[i] == key[i])
 			continue;
@@ -209,15 +202,17 @@ static void *add_to_trie(struct trie *root, const char *key, void *value)
 						   child->len);
 		}
 		child->value = root->value;
-		root->value = NULL;
+		root->value = key[i]
+			? NULL /* Key splits the compressed section. */
+			: value; /* Key matches up to here. */
 		root->len = i;
 
 		memset(root->children, 0, sizeof(root->children));
 		root->children[(unsigned char)root->contents[i]] = child;
 
-		/* This is the newly-added child. */
-		root->children[(unsigned char)key[i]] =
-			make_trie_node(key + i + 1, value);
+		if (key[i])
+			root->children[(unsigned char)key[i]] =
+				make_trie_node(key + i + 1, value);
 		return NULL;
 	}
 
@@ -233,6 +228,8 @@ static void *add_to_trie(struct trie *root, const char *key, void *value)
 		}
 	}
 
+	/* We have matched the entire compressed section with the entire key */
+	assert(!root->value); /* Key already present in the trie? */
 	old = root->value;
 	root->value = value;
 	return old;
-- 
2.36.1
Message 1 of 1 in “path.c: add_to_trie - possible global-buffer-overflow fixed”
  1. path.c: add_to_trie - possible global-buffer-overflow fixedRubén Justo, Oct 17, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.