Merge branch 'ap/path-max'
* ap/path-max: Prevent buffer overflows when path is too long
This commit is contained in:
commit
273c54f82c
16
abspath.c
16
abspath.c
@ -215,23 +215,25 @@ const char *absolute_path(const char *path)
|
|||||||
*/
|
*/
|
||||||
const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
|
const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
|
||||||
{
|
{
|
||||||
static char path[PATH_MAX];
|
static struct strbuf path = STRBUF_INIT;
|
||||||
#ifndef GIT_WINDOWS_NATIVE
|
#ifndef GIT_WINDOWS_NATIVE
|
||||||
if (!pfx_len || is_absolute_path(arg))
|
if (!pfx_len || is_absolute_path(arg))
|
||||||
return arg;
|
return arg;
|
||||||
memcpy(path, pfx, pfx_len);
|
strbuf_reset(&path);
|
||||||
strcpy(path + pfx_len, arg);
|
strbuf_add(&path, pfx, pfx_len);
|
||||||
|
strbuf_addstr(&path, arg);
|
||||||
#else
|
#else
|
||||||
char *p;
|
char *p;
|
||||||
/* don't add prefix to absolute paths, but still replace '\' by '/' */
|
/* don't add prefix to absolute paths, but still replace '\' by '/' */
|
||||||
|
strbuf_reset(&path);
|
||||||
if (is_absolute_path(arg))
|
if (is_absolute_path(arg))
|
||||||
pfx_len = 0;
|
pfx_len = 0;
|
||||||
else if (pfx_len)
|
else if (pfx_len)
|
||||||
memcpy(path, pfx, pfx_len);
|
strbuf_add(&path, pfx, pfx_len);
|
||||||
strcpy(path + pfx_len, arg);
|
strbuf_addstr(&path, arg);
|
||||||
for (p = path + pfx_len; *p; p++)
|
for (p = path.buf + pfx_len; *p; p++)
|
||||||
if (*p == '\\')
|
if (*p == '\\')
|
||||||
*p = '/';
|
*p = '/';
|
||||||
#endif
|
#endif
|
||||||
return path;
|
return path.buf;
|
||||||
}
|
}
|
||||||
|
@ -73,15 +73,16 @@ struct pair_order {
|
|||||||
static int match_order(const char *path)
|
static int match_order(const char *path)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char p[PATH_MAX];
|
static struct strbuf p = STRBUF_INIT;
|
||||||
|
|
||||||
for (i = 0; i < order_cnt; i++) {
|
for (i = 0; i < order_cnt; i++) {
|
||||||
strcpy(p, path);
|
strbuf_reset(&p);
|
||||||
while (p[0]) {
|
strbuf_addstr(&p, path);
|
||||||
|
while (p.buf[0]) {
|
||||||
char *cp;
|
char *cp;
|
||||||
if (!fnmatch(order[i], p, 0))
|
if (!fnmatch(order[i], p.buf, 0))
|
||||||
return i;
|
return i;
|
||||||
cp = strrchr(p, '/');
|
cp = strrchr(p.buf, '/');
|
||||||
if (!cp)
|
if (!cp)
|
||||||
break;
|
break;
|
||||||
*cp = 0;
|
*cp = 0;
|
||||||
|
@ -830,23 +830,24 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int clear_ce_flags_1(struct cache_entry **cache, int nr,
|
static int clear_ce_flags_1(struct cache_entry **cache, int nr,
|
||||||
char *prefix, int prefix_len,
|
struct strbuf *prefix,
|
||||||
int select_mask, int clear_mask,
|
int select_mask, int clear_mask,
|
||||||
struct exclude_list *el, int defval);
|
struct exclude_list *el, int defval);
|
||||||
|
|
||||||
/* Whole directory matching */
|
/* Whole directory matching */
|
||||||
static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
|
static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
|
||||||
char *prefix, int prefix_len,
|
struct strbuf *prefix,
|
||||||
char *basename,
|
char *basename,
|
||||||
int select_mask, int clear_mask,
|
int select_mask, int clear_mask,
|
||||||
struct exclude_list *el, int defval)
|
struct exclude_list *el, int defval)
|
||||||
{
|
{
|
||||||
struct cache_entry **cache_end;
|
struct cache_entry **cache_end;
|
||||||
int dtype = DT_DIR;
|
int dtype = DT_DIR;
|
||||||
int ret = is_excluded_from_list(prefix, prefix_len,
|
int ret = is_excluded_from_list(prefix->buf, prefix->len,
|
||||||
basename, &dtype, el);
|
basename, &dtype, el);
|
||||||
|
int rc;
|
||||||
|
|
||||||
prefix[prefix_len++] = '/';
|
strbuf_addch(prefix, '/');
|
||||||
|
|
||||||
/* If undecided, use matching result of parent dir in defval */
|
/* If undecided, use matching result of parent dir in defval */
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -854,7 +855,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
|
|||||||
|
|
||||||
for (cache_end = cache; cache_end != cache + nr; cache_end++) {
|
for (cache_end = cache; cache_end != cache + nr; cache_end++) {
|
||||||
struct cache_entry *ce = *cache_end;
|
struct cache_entry *ce = *cache_end;
|
||||||
if (strncmp(ce->name, prefix, prefix_len))
|
if (strncmp(ce->name, prefix->buf, prefix->len))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,10 +866,12 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
|
|||||||
* calling clear_ce_flags_1(). That function will call
|
* calling clear_ce_flags_1(). That function will call
|
||||||
* the expensive is_excluded_from_list() on every entry.
|
* the expensive is_excluded_from_list() on every entry.
|
||||||
*/
|
*/
|
||||||
return clear_ce_flags_1(cache, cache_end - cache,
|
rc = clear_ce_flags_1(cache, cache_end - cache,
|
||||||
prefix, prefix_len,
|
prefix,
|
||||||
select_mask, clear_mask,
|
select_mask, clear_mask,
|
||||||
el, ret);
|
el, ret);
|
||||||
|
strbuf_setlen(prefix, prefix->len - 1);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -887,7 +890,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
|
|||||||
* Top level path has prefix_len zero.
|
* Top level path has prefix_len zero.
|
||||||
*/
|
*/
|
||||||
static int clear_ce_flags_1(struct cache_entry **cache, int nr,
|
static int clear_ce_flags_1(struct cache_entry **cache, int nr,
|
||||||
char *prefix, int prefix_len,
|
struct strbuf *prefix,
|
||||||
int select_mask, int clear_mask,
|
int select_mask, int clear_mask,
|
||||||
struct exclude_list *el, int defval)
|
struct exclude_list *el, int defval)
|
||||||
{
|
{
|
||||||
@ -907,10 +910,10 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefix_len && strncmp(ce->name, prefix, prefix_len))
|
if (prefix->len && strncmp(ce->name, prefix->buf, prefix->len))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
name = ce->name + prefix_len;
|
name = ce->name + prefix->len;
|
||||||
slash = strchr(name, '/');
|
slash = strchr(name, '/');
|
||||||
|
|
||||||
/* If it's a directory, try whole directory match first */
|
/* If it's a directory, try whole directory match first */
|
||||||
@ -918,29 +921,26 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
|
|||||||
int processed;
|
int processed;
|
||||||
|
|
||||||
len = slash - name;
|
len = slash - name;
|
||||||
memcpy(prefix + prefix_len, name, len);
|
strbuf_add(prefix, name, len);
|
||||||
|
|
||||||
/*
|
|
||||||
* terminate the string (no trailing slash),
|
|
||||||
* clear_c_f_dir needs it
|
|
||||||
*/
|
|
||||||
prefix[prefix_len + len] = '\0';
|
|
||||||
processed = clear_ce_flags_dir(cache, cache_end - cache,
|
processed = clear_ce_flags_dir(cache, cache_end - cache,
|
||||||
prefix, prefix_len + len,
|
prefix,
|
||||||
prefix + prefix_len,
|
prefix->buf + prefix->len - len,
|
||||||
select_mask, clear_mask,
|
select_mask, clear_mask,
|
||||||
el, defval);
|
el, defval);
|
||||||
|
|
||||||
/* clear_c_f_dir eats a whole dir already? */
|
/* clear_c_f_dir eats a whole dir already? */
|
||||||
if (processed) {
|
if (processed) {
|
||||||
cache += processed;
|
cache += processed;
|
||||||
|
strbuf_setlen(prefix, prefix->len - len);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix[prefix_len + len++] = '/';
|
strbuf_addch(prefix, '/');
|
||||||
cache += clear_ce_flags_1(cache, cache_end - cache,
|
cache += clear_ce_flags_1(cache, cache_end - cache,
|
||||||
prefix, prefix_len + len,
|
prefix,
|
||||||
select_mask, clear_mask, el, defval);
|
select_mask, clear_mask, el, defval);
|
||||||
|
strbuf_setlen(prefix, prefix->len - len - 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,9 +961,12 @@ static int clear_ce_flags(struct cache_entry **cache, int nr,
|
|||||||
int select_mask, int clear_mask,
|
int select_mask, int clear_mask,
|
||||||
struct exclude_list *el)
|
struct exclude_list *el)
|
||||||
{
|
{
|
||||||
char prefix[PATH_MAX];
|
static struct strbuf prefix = STRBUF_INIT;
|
||||||
|
|
||||||
|
strbuf_reset(&prefix);
|
||||||
|
|
||||||
return clear_ce_flags_1(cache, nr,
|
return clear_ce_flags_1(cache, nr,
|
||||||
prefix, 0,
|
&prefix,
|
||||||
select_mask, clear_mask,
|
select_mask, clear_mask,
|
||||||
el, 0);
|
el, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user