Skip to content

Commit 66c8448

Browse files
peffgitster
authored andcommitted
url: decode buffers that are not NUL-terminated
The url_decode function needs only minor tweaks to handle arbitrary buffers. Let's do those tweaks, which cleans up an unreadable mess of temporary strings in http.c. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d79bcd6 commit 66c8448

File tree

3 files changed

+23
-31
lines changed

3 files changed

+23
-31
lines changed

http.c

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,7 @@ static CURL *get_curl_handle(void)
307307

308308
static void http_auth_init(const char *url)
309309
{
310-
char *at, *colon, *cp, *slash, *decoded;
311-
int len;
310+
char *at, *colon, *cp, *slash;
312311

313312
cp = strstr(url, "://");
314313
if (!cp)
@@ -328,29 +327,11 @@ static void http_auth_init(const char *url)
328327
return; /* No credentials */
329328
if (!colon || at <= colon) {
330329
/* Only username */
331-
len = at - cp;
332-
user_name = xmalloc(len + 1);
333-
memcpy(user_name, cp, len);
334-
user_name[len] = '\0';
335-
decoded = url_decode(user_name);
336-
free(user_name);
337-
user_name = decoded;
330+
user_name = url_decode_mem(cp, at - cp);
338331
user_pass = NULL;
339332
} else {
340-
len = colon - cp;
341-
user_name = xmalloc(len + 1);
342-
memcpy(user_name, cp, len);
343-
user_name[len] = '\0';
344-
decoded = url_decode(user_name);
345-
free(user_name);
346-
user_name = decoded;
347-
len = at - (colon + 1);
348-
user_pass = xmalloc(len + 1);
349-
memcpy(user_pass, colon + 1, len);
350-
user_pass[len] = '\0';
351-
decoded = url_decode(user_pass);
352-
free(user_pass);
353-
user_pass = decoded;
333+
user_name = url_decode_mem(cp, colon - cp);
334+
user_pass = url_decode_mem(colon + 1, at - (colon + 1));
354335
}
355336
}
356337

url.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,20 @@ static int url_decode_char(const char *q)
6868
return val;
6969
}
7070

71-
static char *url_decode_internal(const char **query, const char *stop_at,
72-
struct strbuf *out, int decode_plus)
71+
static char *url_decode_internal(const char **query, int len,
72+
const char *stop_at, struct strbuf *out,
73+
int decode_plus)
7374
{
7475
const char *q = *query;
7576

76-
do {
77+
while (len) {
7778
unsigned char c = *q;
7879

7980
if (!c)
8081
break;
8182
if (stop_at && strchr(stop_at, c)) {
8283
q++;
84+
len--;
8385
break;
8486
}
8587

@@ -88,6 +90,7 @@ static char *url_decode_internal(const char **query, const char *stop_at,
8890
if (0 <= val) {
8991
strbuf_addch(out, val);
9092
q += 3;
93+
len -= 3;
9194
continue;
9295
}
9396
}
@@ -97,34 +100,41 @@ static char *url_decode_internal(const char **query, const char *stop_at,
97100
else
98101
strbuf_addch(out, c);
99102
q++;
100-
} while (1);
103+
len--;
104+
}
101105
*query = q;
102106
return strbuf_detach(out, NULL);
103107
}
104108

105109
char *url_decode(const char *url)
110+
{
111+
return url_decode_mem(url, strlen(url));
112+
}
113+
114+
char *url_decode_mem(const char *url, int len)
106115
{
107116
struct strbuf out = STRBUF_INIT;
108-
const char *colon = strchr(url, ':');
117+
const char *colon = memchr(url, ':', len);
109118

110119
/* Skip protocol part if present */
111120
if (colon && url < colon) {
112121
strbuf_add(&out, url, colon - url);
122+
len -= colon - url;
113123
url = colon;
114124
}
115-
return url_decode_internal(&url, NULL, &out, 0);
125+
return url_decode_internal(&url, len, NULL, &out, 0);
116126
}
117127

118128
char *url_decode_parameter_name(const char **query)
119129
{
120130
struct strbuf out = STRBUF_INIT;
121-
return url_decode_internal(query, "&=", &out, 1);
131+
return url_decode_internal(query, -1, "&=", &out, 1);
122132
}
123133

124134
char *url_decode_parameter_value(const char **query)
125135
{
126136
struct strbuf out = STRBUF_INIT;
127-
return url_decode_internal(query, "&", &out, 1);
137+
return url_decode_internal(query, -1, "&", &out, 1);
128138
}
129139

130140
void end_url_with_slash(struct strbuf *buf, const char *url)

url.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
extern int is_url(const char *url);
55
extern int is_urlschemechar(int first_flag, int ch);
66
extern char *url_decode(const char *url);
7+
extern char *url_decode_mem(const char *url, int len);
78
extern char *url_decode_parameter_name(const char **query);
89
extern char *url_decode_parameter_value(const char **query);
910

0 commit comments

Comments
 (0)