зеркало из https://github.com/microsoft/git.git
path.c: make get_pathname() return strbuf instead of static buffer
We've been avoiding PATH_MAX whenever possible. This patch makes get_pathname() return a strbuf and updates the callers to take advantage of this. The code is simplified as we no longer need to worry about buffer overflow. vsnpath() behavior is changed slightly: previously it always clears the buffer before writing, now it just appends. Fortunately this is a static function and all of its callers prepare the buffer properly: git_path() gets the buffer from get_pathname() which resets the buffer, the remaining call sites start with STRBUF_INIT'd buffer. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
b260d265e1
Коммит
4ef9caf543
120
path.c
120
path.c
|
@ -16,11 +16,15 @@ static int get_st_mode_bits(const char *path, int *mode)
|
||||||
|
|
||||||
static char bad_path[] = "/bad-path/";
|
static char bad_path[] = "/bad-path/";
|
||||||
|
|
||||||
static char *get_pathname(void)
|
static struct strbuf *get_pathname(void)
|
||||||
{
|
{
|
||||||
static char pathname_array[4][PATH_MAX];
|
static struct strbuf pathname_array[4] = {
|
||||||
|
STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
|
||||||
|
};
|
||||||
static int index;
|
static int index;
|
||||||
return pathname_array[3 & ++index];
|
struct strbuf *sb = &pathname_array[3 & ++index];
|
||||||
|
strbuf_reset(sb);
|
||||||
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *cleanup_path(char *path)
|
static char *cleanup_path(char *path)
|
||||||
|
@ -34,6 +38,13 @@ static char *cleanup_path(char *path)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void strbuf_cleanup_path(struct strbuf *sb)
|
||||||
|
{
|
||||||
|
char *path = cleanup_path(sb->buf);
|
||||||
|
if (path > sb->buf)
|
||||||
|
strbuf_remove(sb, 0, path - sb->buf);
|
||||||
|
}
|
||||||
|
|
||||||
char *mksnpath(char *buf, size_t n, const char *fmt, ...)
|
char *mksnpath(char *buf, size_t n, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
@ -49,85 +60,70 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
|
||||||
return cleanup_path(buf);
|
return cleanup_path(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *vsnpath(char *buf, size_t n, const char *fmt, va_list args)
|
static void vsnpath(struct strbuf *buf, const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
const char *git_dir = get_git_dir();
|
const char *git_dir = get_git_dir();
|
||||||
size_t len;
|
strbuf_addstr(buf, git_dir);
|
||||||
|
if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
|
||||||
len = strlen(git_dir);
|
strbuf_addch(buf, '/');
|
||||||
if (n < len + 1)
|
strbuf_vaddf(buf, fmt, args);
|
||||||
goto bad;
|
strbuf_cleanup_path(buf);
|
||||||
memcpy(buf, git_dir, len);
|
|
||||||
if (len && !is_dir_sep(git_dir[len-1]))
|
|
||||||
buf[len++] = '/';
|
|
||||||
len += vsnprintf(buf + len, n - len, fmt, args);
|
|
||||||
if (len >= n)
|
|
||||||
goto bad;
|
|
||||||
return cleanup_path(buf);
|
|
||||||
bad:
|
|
||||||
strlcpy(buf, bad_path, n);
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *git_snpath(char *buf, size_t n, const char *fmt, ...)
|
char *git_snpath(char *buf, size_t n, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char *ret;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
ret = vsnpath(buf, n, fmt, args);
|
vsnpath(&sb, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return ret;
|
if (sb.len >= n)
|
||||||
|
strlcpy(buf, bad_path, n);
|
||||||
|
else
|
||||||
|
memcpy(buf, sb.buf, sb.len + 1);
|
||||||
|
strbuf_release(&sb);
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *git_pathdup(const char *fmt, ...)
|
char *git_pathdup(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX], *ret;
|
struct strbuf path = STRBUF_INIT;
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
ret = vsnpath(path, sizeof(path), fmt, args);
|
vsnpath(&path, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return xstrdup(ret);
|
return strbuf_detach(&path, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mkpathdup(const char *fmt, ...)
|
char *mkpathdup(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char *path;
|
|
||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
strbuf_vaddf(&sb, fmt, args);
|
strbuf_vaddf(&sb, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
path = xstrdup(cleanup_path(sb.buf));
|
strbuf_cleanup_path(&sb);
|
||||||
|
return strbuf_detach(&sb, NULL);
|
||||||
strbuf_release(&sb);
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mkpath(const char *fmt, ...)
|
char *mkpath(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
unsigned len;
|
struct strbuf *pathname = get_pathname();
|
||||||
char *pathname = get_pathname();
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
len = vsnprintf(pathname, PATH_MAX, fmt, args);
|
strbuf_vaddf(pathname, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (len >= PATH_MAX)
|
return cleanup_path(pathname->buf);
|
||||||
return bad_path;
|
|
||||||
return cleanup_path(pathname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *git_path(const char *fmt, ...)
|
char *git_path(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char *pathname = get_pathname();
|
struct strbuf *pathname = get_pathname();
|
||||||
va_list args;
|
va_list args;
|
||||||
char *ret;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
ret = vsnpath(pathname, PATH_MAX, fmt, args);
|
vsnpath(pathname, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return ret;
|
return pathname->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void home_config_paths(char **global, char **xdg, char *file)
|
void home_config_paths(char **global, char **xdg, char *file)
|
||||||
|
@ -160,41 +156,27 @@ void home_config_paths(char **global, char **xdg, char *file)
|
||||||
|
|
||||||
char *git_path_submodule(const char *path, const char *fmt, ...)
|
char *git_path_submodule(const char *path, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char *pathname = get_pathname();
|
struct strbuf *buf = get_pathname();
|
||||||
struct strbuf buf = STRBUF_INIT;
|
|
||||||
const char *git_dir;
|
const char *git_dir;
|
||||||
va_list args;
|
va_list args;
|
||||||
unsigned len;
|
|
||||||
|
|
||||||
len = strlen(path);
|
strbuf_addstr(buf, path);
|
||||||
if (len > PATH_MAX-100)
|
if (buf->len && buf->buf[buf->len - 1] != '/')
|
||||||
return bad_path;
|
strbuf_addch(buf, '/');
|
||||||
|
strbuf_addstr(buf, ".git");
|
||||||
|
|
||||||
strbuf_addstr(&buf, path);
|
git_dir = read_gitfile(buf->buf);
|
||||||
if (len && path[len-1] != '/')
|
|
||||||
strbuf_addch(&buf, '/');
|
|
||||||
strbuf_addstr(&buf, ".git");
|
|
||||||
|
|
||||||
git_dir = read_gitfile(buf.buf);
|
|
||||||
if (git_dir) {
|
if (git_dir) {
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(buf);
|
||||||
strbuf_addstr(&buf, git_dir);
|
strbuf_addstr(buf, git_dir);
|
||||||
}
|
}
|
||||||
strbuf_addch(&buf, '/');
|
strbuf_addch(buf, '/');
|
||||||
|
|
||||||
if (buf.len >= PATH_MAX)
|
|
||||||
return bad_path;
|
|
||||||
memcpy(pathname, buf.buf, buf.len + 1);
|
|
||||||
|
|
||||||
strbuf_release(&buf);
|
|
||||||
len = strlen(pathname);
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
|
strbuf_vaddf(buf, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (len >= PATH_MAX)
|
strbuf_cleanup_path(buf);
|
||||||
return bad_path;
|
return buf->buf;
|
||||||
return cleanup_path(pathname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int validate_headref(const char *path)
|
int validate_headref(const char *path)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче