Skip to content

Commit 4ef9caf

Browse files
pcloudsgitster
authored andcommitted
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>
1 parent b260d26 commit 4ef9caf

File tree

1 file changed

+51
-69
lines changed

1 file changed

+51
-69
lines changed

path.c

Lines changed: 51 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@ static int get_st_mode_bits(const char *path, int *mode)
1616

1717
static char bad_path[] = "/bad-path/";
1818

19-
static char *get_pathname(void)
19+
static struct strbuf *get_pathname(void)
2020
{
21-
static char pathname_array[4][PATH_MAX];
21+
static struct strbuf pathname_array[4] = {
22+
STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
23+
};
2224
static int index;
23-
return pathname_array[3 & ++index];
25+
struct strbuf *sb = &pathname_array[3 & ++index];
26+
strbuf_reset(sb);
27+
return sb;
2428
}
2529

2630
static char *cleanup_path(char *path)
@@ -34,6 +38,13 @@ static char *cleanup_path(char *path)
3438
return path;
3539
}
3640

41+
static void strbuf_cleanup_path(struct strbuf *sb)
42+
{
43+
char *path = cleanup_path(sb->buf);
44+
if (path > sb->buf)
45+
strbuf_remove(sb, 0, path - sb->buf);
46+
}
47+
3748
char *mksnpath(char *buf, size_t n, const char *fmt, ...)
3849
{
3950
va_list args;
@@ -49,85 +60,70 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
4960
return cleanup_path(buf);
5061
}
5162

52-
static char *vsnpath(char *buf, size_t n, const char *fmt, va_list args)
63+
static void vsnpath(struct strbuf *buf, const char *fmt, va_list args)
5364
{
5465
const char *git_dir = get_git_dir();
55-
size_t len;
56-
57-
len = strlen(git_dir);
58-
if (n < len + 1)
59-
goto bad;
60-
memcpy(buf, git_dir, len);
61-
if (len && !is_dir_sep(git_dir[len-1]))
62-
buf[len++] = '/';
63-
len += vsnprintf(buf + len, n - len, fmt, args);
64-
if (len >= n)
65-
goto bad;
66-
return cleanup_path(buf);
67-
bad:
68-
strlcpy(buf, bad_path, n);
69-
return buf;
66+
strbuf_addstr(buf, git_dir);
67+
if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
68+
strbuf_addch(buf, '/');
69+
strbuf_vaddf(buf, fmt, args);
70+
strbuf_cleanup_path(buf);
7071
}
7172

7273
char *git_snpath(char *buf, size_t n, const char *fmt, ...)
7374
{
74-
char *ret;
75+
struct strbuf sb = STRBUF_INIT;
7576
va_list args;
7677
va_start(args, fmt);
77-
ret = vsnpath(buf, n, fmt, args);
78+
vsnpath(&sb, fmt, args);
7879
va_end(args);
79-
return ret;
80+
if (sb.len >= n)
81+
strlcpy(buf, bad_path, n);
82+
else
83+
memcpy(buf, sb.buf, sb.len + 1);
84+
strbuf_release(&sb);
85+
return buf;
8086
}
8187

8288
char *git_pathdup(const char *fmt, ...)
8389
{
84-
char path[PATH_MAX], *ret;
90+
struct strbuf path = STRBUF_INIT;
8591
va_list args;
8692
va_start(args, fmt);
87-
ret = vsnpath(path, sizeof(path), fmt, args);
93+
vsnpath(&path, fmt, args);
8894
va_end(args);
89-
return xstrdup(ret);
95+
return strbuf_detach(&path, NULL);
9096
}
9197

9298
char *mkpathdup(const char *fmt, ...)
9399
{
94-
char *path;
95100
struct strbuf sb = STRBUF_INIT;
96101
va_list args;
97-
98102
va_start(args, fmt);
99103
strbuf_vaddf(&sb, fmt, args);
100104
va_end(args);
101-
path = xstrdup(cleanup_path(sb.buf));
102-
103-
strbuf_release(&sb);
104-
return path;
105+
strbuf_cleanup_path(&sb);
106+
return strbuf_detach(&sb, NULL);
105107
}
106108

107109
char *mkpath(const char *fmt, ...)
108110
{
109111
va_list args;
110-
unsigned len;
111-
char *pathname = get_pathname();
112-
112+
struct strbuf *pathname = get_pathname();
113113
va_start(args, fmt);
114-
len = vsnprintf(pathname, PATH_MAX, fmt, args);
114+
strbuf_vaddf(pathname, fmt, args);
115115
va_end(args);
116-
if (len >= PATH_MAX)
117-
return bad_path;
118-
return cleanup_path(pathname);
116+
return cleanup_path(pathname->buf);
119117
}
120118

121119
char *git_path(const char *fmt, ...)
122120
{
123-
char *pathname = get_pathname();
121+
struct strbuf *pathname = get_pathname();
124122
va_list args;
125-
char *ret;
126-
127123
va_start(args, fmt);
128-
ret = vsnpath(pathname, PATH_MAX, fmt, args);
124+
vsnpath(pathname, fmt, args);
129125
va_end(args);
130-
return ret;
126+
return pathname->buf;
131127
}
132128

133129
void home_config_paths(char **global, char **xdg, char *file)
@@ -160,41 +156,27 @@ void home_config_paths(char **global, char **xdg, char *file)
160156

161157
char *git_path_submodule(const char *path, const char *fmt, ...)
162158
{
163-
char *pathname = get_pathname();
164-
struct strbuf buf = STRBUF_INIT;
159+
struct strbuf *buf = get_pathname();
165160
const char *git_dir;
166161
va_list args;
167-
unsigned len;
168-
169-
len = strlen(path);
170-
if (len > PATH_MAX-100)
171-
return bad_path;
172162

173-
strbuf_addstr(&buf, path);
174-
if (len && path[len-1] != '/')
175-
strbuf_addch(&buf, '/');
176-
strbuf_addstr(&buf, ".git");
163+
strbuf_addstr(buf, path);
164+
if (buf->len && buf->buf[buf->len - 1] != '/')
165+
strbuf_addch(buf, '/');
166+
strbuf_addstr(buf, ".git");
177167

178-
git_dir = read_gitfile(buf.buf);
168+
git_dir = read_gitfile(buf->buf);
179169
if (git_dir) {
180-
strbuf_reset(&buf);
181-
strbuf_addstr(&buf, git_dir);
170+
strbuf_reset(buf);
171+
strbuf_addstr(buf, git_dir);
182172
}
183-
strbuf_addch(&buf, '/');
184-
185-
if (buf.len >= PATH_MAX)
186-
return bad_path;
187-
memcpy(pathname, buf.buf, buf.len + 1);
188-
189-
strbuf_release(&buf);
190-
len = strlen(pathname);
173+
strbuf_addch(buf, '/');
191174

192175
va_start(args, fmt);
193-
len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
176+
strbuf_vaddf(buf, fmt, args);
194177
va_end(args);
195-
if (len >= PATH_MAX)
196-
return bad_path;
197-
return cleanup_path(pathname);
178+
strbuf_cleanup_path(buf);
179+
return buf->buf;
198180
}
199181

200182
int validate_headref(const char *path)

0 commit comments

Comments
 (0)