threads / patch / 15784

patchmake prefix_path() never return NULL

Subject: [PATCH] make prefix_path() never return NULL

## tl;dr

7 messages between Oct 5, 2008 and Oct 11, 2008. Diffs are folded; open one to read it.

replies: 6people: 2as markdown or json

Dmitry Potapov· Oct 5, 2008, 00:40 UTC · lore
There are 9 places where prefix_path is called, and only in one of
them the returned pointer was checked to be non-zero and only to
call exit(128) as it is usually done by die(). In other 8 places,
the returned value was not checked and it caused SIGSEGV when a
path outside of the working tree was used. For instance, running
  git update-index --add /some/path/outside
caused SIGSEGV.

This patch changes prefix_path() to die if the path is outside of the repository, so it never returns NULL.

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---
 setup.c |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)
Show changes to setup.c +2 −7
diff --git a/setup.c b/setup.c
index 2e3248a..78a8041 100644
--- a/setup.c
+++ b/setup.c
@@ -110,9 +110,7 @@ const char *prefix_path(const char *prefix, int len, const char *path)
 		if (strncmp(sanitized, work_tree, len) ||
 		    (sanitized[len] != '\0' && sanitized[len] != '/')) {
 		error_out:
-			error("'%s' is outside repository", orig);
-			free(sanitized);
-			return NULL;
+			die("'%s' is outside repository", orig);
 		}
 		if (sanitized[len] == '/')
 			len++;
@@ -216,10 +214,7 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
 	prefixlen = prefix ? strlen(prefix) : 0;
 	while (*src) {
 		const char *p = prefix_path(prefix, prefixlen, *src);
-		if (p)
-			*(dst++) = p;
-		else
-			exit(128); /* error message already given */
+		*(dst++) = p;
 		src++;
 	}
 	*dst = NULL;
-- 
1.6.0.2.445.g1198
Dmitry Potapov· Oct 5, 2008, 02:14 UTC · re: Dmitry Potapov · lore

[PATCH] do not segfault if make_cache_entry failed

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---
 builtin-apply.c    |    2 ++
 builtin-checkout.c |    2 ++
 builtin-reset.c    |    3 +++
 3 files changed, 7 insertions(+), 0 deletions(-)
Show changes to 3 files +7 −0

builtin-apply.c, builtin-checkout.c, builtin-reset.c

diff --git a/builtin-apply.c b/builtin-apply.c
index e2c611b..342f2fe 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -2586,6 +2586,8 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
 			sha1_ptr = sha1;
 
 		ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0);
+		if (!ce)
+			die("make_cache_entry failed for path '%s'", name);
 		if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
 			die ("Could not add %s to temporary index", name);
 	}
diff --git a/builtin-checkout.c b/builtin-checkout.c
index b572b3b..3762f71 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -206,6 +206,8 @@ static int checkout_merged(int pos, struct checkout *state)
 	ce = make_cache_entry(create_ce_mode(active_cache[pos+1]->ce_mode),
 			      sha1,
 			      path, 2, 0);
+	if (!ce)
+		die("make_cache_entry failed for path '%s'", path);
 	status = checkout_entry(ce, state, NULL);
 	return status;
 }
diff --git a/builtin-reset.c b/builtin-reset.c
index c24c219..16e6bb2 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -121,6 +121,9 @@ static void update_index_from_diff(struct diff_queue_struct *q,
 			struct cache_entry *ce;
 			ce = make_cache_entry(one->mode, one->sha1, one->path,
 				0, 0);
+			if (!ce)
+				die("make_cache_entry failed for path '%s'",
+				    one->path);
 			add_cache_entry(ce, ADD_CACHE_OK_TO_ADD |
 				ADD_CACHE_OK_TO_REPLACE);
 		} else
-- 
1.6.0
Dmitry Potapov· Oct 5, 2008, 02:14 UTC · re: Dmitry Potapov · lore

[PATCH] error out if path is invalid

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---
 builtin-update-index.c |    2 +-
 read-cache.c           |    6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)
Show changes to 2 files +5 −3

builtin-update-index.c, read-cache.c

diff --git a/builtin-update-index.c b/builtin-update-index.c
index 417f972..3a2291b 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -218,7 +218,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
 	struct cache_entry *ce;
 
 	if (!verify_path(path))
-		return -1;
+		return error("Invalid path '%s'", path);
 
 	len = strlen(path);
 	size = cache_entry_size(len);
diff --git a/read-cache.c b/read-cache.c
index 972592e..43dc338 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -591,8 +591,10 @@ struct cache_entry *make_cache_entry(unsigned int mode,
 	int size, len;
 	struct cache_entry *ce;
 
-	if (!verify_path(path))
+	if (!verify_path(path)) {
+		error("Invalid path '%s'", path);
 		return NULL;
+	}
 
 	len = strlen(path);
 	size = cache_entry_size(len);
@@ -884,7 +886,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 	if (!ok_to_add)
 		return -1;
 	if (!verify_path(ce->name))
-		return -1;
+		return error("Invalid path '%s'", ce->name);
 
 	if (!skip_df_check &&
 	    check_file_directory_conflict(istate, ce, pos, ok_to_replace)) {
-- 
1.6.0
Johannes Sixt· Oct 6, 2008, 07:02 UTC · re: Dmitry Potapov · lore

Re: [PATCH] error out if path is invalid

Dmitry Potapov schrieb:
>  	if (!verify_path(path))
> -		return -1;
> +		return error("Invalid path '%s'", path);

Look at this change. Didn't the code error out before, too? Same in the other cases. Hence, your patch subject does not describe the patch. And I'd appreciate if you could at least show an example in the description what the patch fixes.

-- Hannes
Dmitry Potapov· Oct 7, 2008, 00:22 UTC · re: Johannes Sixt · lore

Re: [PATCH] error out if path is invalid

On Mon, Oct 06, 2008 at 09:02:22AM +0200, Johannes Sixt wrote:
Show 6 quoted lines
> Dmitry Potapov schrieb:
> >  	if (!verify_path(path))
> > -		return -1;
> > +		return error("Invalid path '%s'", path);
> 
> Look at this change. Didn't the code error out before, too?
It is certainly did not here. As to its caller, it depends. In fact,
there are two chunks like that in my patch, so I am not sure to which
one you refer here. If we speak about add_cacheinfo() then though the
function did not error out, its caller died with one of the following
messages:
  git update-index: unable to update some-file-name
or
  git update-index: --cacheinfo cannot add some-file-name

However, if we speak about add_index_entry_with_check then the caller will not produce any error. The git would exit successfully (it still does) and there was no error message as if everything was fine.

Perhaps, the exit code should be corrected too, but if the git just dies when add_index_entry() fails it may cause that having one invalid path will prevent to check out other files, which does not seem to be the right thing to do.

As to correction to correction to make_cache_entry then after my previous patch, it started to error out:

  make_cache_entry failed for path 'some-file-name'
before that it silently segfaulted.
> Same in the
> other cases. Hence, your patch subject does not describe the patch.

Should I include the above explanation in the commit message or do you have any objection to having the above error message in cases where the caller already produce some message when it dies?

Dmitry
Johannes Sixt· Oct 7, 2008, 06:03 UTC · re: Dmitry Potapov · lore

Re: [PATCH] error out if path is invalid

Dmitry Potapov schrieb:
Show 15 quoted lines
> On Mon, Oct 06, 2008 at 09:02:22AM +0200, Johannes Sixt wrote:
>> Dmitry Potapov schrieb:
>>>  	if (!verify_path(path))
>>> -		return -1;
>>> +		return error("Invalid path '%s'", path);
>> Look at this change. Didn't the code error out before, too?
> 
> It is certainly did not here. As to its caller, it depends. In fact,
> there are two chunks like that in my patch, so I am not sure to which
> one you refer here. If we speak about add_cacheinfo() then though the
> function did not error out, its caller died with one of the following
> messages:
>   git update-index: unable to update some-file-name
> or
>   git update-index: --cacheinfo cannot add some-file-name

Look at the original patch. You did not change the behavior except to write more error messages. Maybe I misunderstand the words "to error out". I understand them as "to detect an error and return early", but not "write an error message".

Show 22 quoted lines
> However, if we speak about add_index_entry_with_check then the caller
> will not produce any error. The git would exit successfully (it still
> does) and there was no error message as if everything was fine.
> 
> Perhaps, the exit code should be corrected too, but if the git just dies
> when add_index_entry() fails it may cause that having one invalid path
> will prevent to check out other files, which does not seem to be the
> right thing to do.
> 
> As to correction to correction to make_cache_entry then after my
> previous patch, it started to error out:
> 
>   make_cache_entry failed for path 'some-file-name'
> 
> before that it silently segfaulted.
> 
>> Same in the
>> other cases. Hence, your patch subject does not describe the patch.
> 
> Should I include the above explanation in the commit message or do you
> have any objection to having the above error message in cases where the
> caller already produce some message when it dies?

I don't object the change, only its (missing or IMHO incorrect) justification. I don't think that the above text would be the correct description because as far as I can see the only change you made was to add error messages.

-- Hannes
Dmitry Potapov· Oct 11, 2008, 16:39 UTC · re: Johannes Sixt · lore

[PATCH] print an error message for invalid path

If verification of path failed, it is always better to print an error message saying this than relying on the caller function to print a meaningful error message (especially when the callee already prints error message for another situation).

Because the callers of add_index_entry_with_check() did not print any error message, it resulted that the user would not notice the problem when checkout if an invalid path failed.

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---
On Tue, Oct 07, 2008 at 08:03:46AM +0200, Johannes Sixt wrote:
Show 5 quoted lines
> 
> Look at the original patch. You did not change the behavior except to
> write more error messages. Maybe I misunderstand the words "to error out".
> I understand them as "to detect an error and return early", but not "write
> an error message".

For me, to "error out" means to show an error to the user. Usually, it implies that the program will return after that, though not necessary immediately. (Like gcc may print an error but it continues to parse the program and may report more errors).

You are right that I have not changed anything in terms of exiting earlier, and because I am aware about any commonly accepted definition of what "error out" means, I have replaced the comment with less ambiguous and detail description.

 builtin-update-index.c |    2 +-
 read-cache.c           |    6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)
Show changes to 2 files +5 −3

builtin-update-index.c, read-cache.c

diff --git a/builtin-update-index.c b/builtin-update-index.c
index 417f972..3a2291b 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -218,7 +218,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
 	struct cache_entry *ce;
 
 	if (!verify_path(path))
-		return -1;
+		return error("Invalid path '%s'", path);
 
 	len = strlen(path);
 	size = cache_entry_size(len);
diff --git a/read-cache.c b/read-cache.c
index 901064b..aff6390 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -591,8 +591,10 @@ struct cache_entry *make_cache_entry(unsigned int mode,
 	int size, len;
 	struct cache_entry *ce;
 
-	if (!verify_path(path))
+	if (!verify_path(path)) {
+		error("Invalid path '%s'", path);
 		return NULL;
+	}
 
 	len = strlen(path);
 	size = cache_entry_size(len);
@@ -874,7 +876,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 	if (!ok_to_add)
 		return -1;
 	if (!verify_path(ce->name))
-		return -1;
+		return error("Invalid path '%s'", ce->name);
 
 	if (!skip_df_check &&
 	    check_file_directory_conflict(istate, ce, pos, ok_to_replace)) {
-- 
1.6.0.2.447.g64b01

← back to recent threads