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

parse-options: avoid arithmetic on pointer that's potentially NULL

From
René Scharfe <l.s.r@web.de>
Date
Nov 12, 2019, 21:41 UTC
Message-ID
<39a0b622-f725-9284-ea50-19cf4078209d@web.de>

parse_options_dup() counts the number of elements in the given array without the end marker, allocates enough memory to hold all of them plus an end marker, then copies them and terminates the new array. The counting part is done by advancing a pointer through the array, and the original pointer is reconstructed using pointer subtraction before the copy operation.

The function is also prepared to handle a NULL pointer passed to it. None of its callers do that currently, but this feature was used by 46e91b663b ("checkout: split part of it to new command 'restore'", 2019-04-25); it seems worth keeping.

It ends up doing arithmetic on that NULL pointer, though, which is undefined in standard C, when it tries to calculate "NULL - 0". Better avoid doing that by remembering the originally given pointer value.

There is another issue, though. memcpy(3) does not support NULL pointers, even for empty arrays. Use COPY_ARRAY instead, which does support such empty arrays. Its call is also shorter and safer by inferring the element type automatically.

Coccinelle and contrib/coccinelle/array.cocci did not propose to use COPY_ARRAY because of the pointer subtraction and because the source is const -- the semantic patch cautiously only considers pointers and array references of the same type.

Signed-off-by: René Scharfe <l.s.r@web.de>
---
Patch formatted with --function-context for easier review.
 parse-options-cb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/parse-options-cb.c b/parse-options-cb.c
index 1240a8514e..c2062ae742 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -161,17 +161,18 @@ int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)

 struct option *parse_options_dup(const struct option *o)
 {
+	const struct option *orig = o;
 	struct option *opts;
 	int nr = 0;

 	while (o && o->type != OPTION_END) {
 		nr++;
 		o++;
 	}

 	ALLOC_ARRAY(opts, nr + 1);
-	memcpy(opts, o - nr, sizeof(*o) * nr);
+	COPY_ARRAY(opts, orig, nr);
 	memset(opts + nr, 0, sizeof(*opts));
 	opts[nr].type = OPTION_END;
 	return opts;
 }
--
2.24.0
Next: Junio C Hamano
Message 1 of 5 in “parse-options: avoid arithmetic on pointer that's potentially NULL”
  1. René ScharfeNov 12, 2019
  2. Junio C HamanoNov 13, 2019
  3. René ScharfeNov 13, 2019
  4. Martin ÅgrenNov 13, 2019
  5. René ScharfeNov 14, 2019

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.