Commit 8dcf39c4 authored by Linus Torvalds's avatar Linus Torvalds Committed by Junio C Hamano

Prevent bogus paths from being added to the index.

With this one, it's now a fatal error to try to add a pathname
that cannot be added with "git add", i.e.

	[[email protected] git]$ git add .git/config
	fatal: unable to add .git/config to index

and

	[[email protected] git]$ git add foo/../bar
	fatal: unable to add foo/../bar to index

instead of the old "Ignoring path xyz" warning that would end up
silently succeeding on any other paths.
Signed-off-by: default avatarLinus Torvalds <[email protected]>
Signed-off-by: default avatarJunio C Hamano <[email protected]>
parent e8f990b4
......@@ -142,6 +142,7 @@ extern void verify_non_filename(const char *prefix, const char *name);
/* Initialize and use the cache information */
extern int read_cache(void);
extern int write_cache(int newfd, struct cache_entry **cache, int entries);
extern int verify_path(const char *path);
extern int cache_name_pos(const char *name, int namelen);
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
......
......@@ -331,6 +331,70 @@ int ce_path_match(const struct cache_entry *ce, const char **pathspec)
return 0;
}
/*
* We fundamentally don't like some paths: we don't want
* dot or dot-dot anywhere, and for obvious reasons don't
* want to recurse into ".git" either.
*
* Also, we don't want double slashes or slashes at the
* end that can make pathnames ambiguous.
*/
static int verify_dotfile(const char *rest)
{
/*
* The first character was '.', but that
* has already been discarded, we now test
* the rest.
*/
switch (*rest) {
/* "." is not allowed */
case '\0': case '/':
return 0;
/*
* ".git" followed by NUL or slash is bad. This
* shares the path end test with the ".." case.
*/
case 'g':
if (rest[1] != 'i')
break;
if (rest[2] != 't')
break;
rest += 2;
/* fallthrough */
case '.':
if (rest[1] == '\0' || rest[1] == '/')
return 0;
}
return 1;
}
int verify_path(const char *path)
{
char c;
goto inside;
for (;;) {
if (!c)
return 1;
if (c == '/') {
inside:
c = *path++;
switch (c) {
default:
continue;
case '/': case '\0':
break;
case '.':
if (verify_dotfile(path))
continue;
}
return 0;
}
c = *path++;
}
}
/*
* Do we have another file that has the beginning components being a
* proper superset of the name we're trying to add?
......@@ -472,6 +536,8 @@ int add_cache_entry(struct cache_entry *ce, int option)
if (!ok_to_add)
return -1;
if (!verify_path(ce->name))
return -1;
if (!skip_df_check &&
check_file_directory_conflict(ce, pos, ok_to_replace)) {
......
......@@ -237,70 +237,6 @@ static int refresh_cache(int really)
return has_errors;
}
/*
* We fundamentally don't like some paths: we don't want
* dot or dot-dot anywhere, and for obvious reasons don't
* want to recurse into ".git" either.
*
* Also, we don't want double slashes or slashes at the
* end that can make pathnames ambiguous.
*/
static int verify_dotfile(const char *rest)
{
/*
* The first character was '.', but that
* has already been discarded, we now test
* the rest.
*/
switch (*rest) {
/* "." is not allowed */
case '\0': case '/':
return 0;
/*
* ".git" followed by NUL or slash is bad. This
* shares the path end test with the ".." case.
*/
case 'g':
if (rest[1] != 'i')
break;
if (rest[2] != 't')
break;
rest += 2;
/* fallthrough */
case '.':
if (rest[1] == '\0' || rest[1] == '/')
return 0;
}
return 1;
}
static int verify_path(const char *path)
{
char c;
goto inside;
for (;;) {
if (!c)
return 1;
if (c == '/') {
inside:
c = *path++;
switch (c) {
default:
continue;
case '/': case '\0':
break;
case '.':
if (verify_dotfile(path))
continue;
}
return 0;
}
c = *path++;
}
}
static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
const char *path, int stage)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment