Skip to content

Commit 835c4d3

Browse files
dturner-twgitster
authored andcommitted
http.c: use CURLOPT_RANGE for range requests
A HTTP server is permitted to return a non-range response to a HTTP range request (and Apache httpd in fact does this in some cases). While libcurl knows how to correctly handle this (by skipping bytes before and after the requested range), it only turns on this handling if it is aware that a range request is being made. By manually setting the range header instead of using CURLOPT_RANGE, we were hiding the fact that this was a range request from libcurl. This could cause corruption. Signed-off-by: David Turner <[email protected]> Reviewed-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2635c2b commit 835c4d3

File tree

2 files changed

+12
-22
lines changed

2 files changed

+12
-22
lines changed

http.c

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ static CURL *curl_default;
3030
#endif
3131

3232
#define PREV_BUF_SIZE 4096
33-
#define RANGE_HEADER_SIZE 30
3433

3534
char curl_errorstr[CURL_ERROR_SIZE];
3635

@@ -681,6 +680,7 @@ struct active_request_slot *get_active_slot(void)
681680
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
682681
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
683682
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
683+
curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL);
684684
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
685685
curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
686686
#endif
@@ -1173,6 +1173,13 @@ static const char *get_accept_language(void)
11731173
return cached_accept_language;
11741174
}
11751175

1176+
static void http_opt_request_remainder(CURL *curl, off_t pos)
1177+
{
1178+
char buf[128];
1179+
xsnprintf(buf, sizeof(buf), "%"PRIuMAX"-", (uintmax_t)pos);
1180+
curl_easy_setopt(curl, CURLOPT_RANGE, buf);
1181+
}
1182+
11761183
/* http_request() targets */
11771184
#define HTTP_REQUEST_STRBUF 0
11781185
#define HTTP_REQUEST_FILE 1
@@ -1201,11 +1208,8 @@ static int http_request(const char *url,
12011208
long posn = ftell(result);
12021209
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
12031210
fwrite);
1204-
if (posn > 0) {
1205-
strbuf_addf(&buf, "Range: bytes=%ld-", posn);
1206-
headers = curl_slist_append(headers, buf.buf);
1207-
strbuf_reset(&buf);
1208-
}
1211+
if (posn > 0)
1212+
http_opt_request_remainder(slot->curl, posn);
12091213
} else
12101214
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
12111215
fwrite_buffer);
@@ -1515,10 +1519,6 @@ void release_http_pack_request(struct http_pack_request *preq)
15151519
fclose(preq->packfile);
15161520
preq->packfile = NULL;
15171521
}
1518-
if (preq->range_header != NULL) {
1519-
curl_slist_free_all(preq->range_header);
1520-
preq->range_header = NULL;
1521-
}
15221522
preq->slot = NULL;
15231523
free(preq->url);
15241524
free(preq);
@@ -1582,7 +1582,6 @@ struct http_pack_request *new_http_pack_request(
15821582
struct packed_git *target, const char *base_url)
15831583
{
15841584
long prev_posn = 0;
1585-
char range[RANGE_HEADER_SIZE];
15861585
struct strbuf buf = STRBUF_INIT;
15871586
struct http_pack_request *preq;
15881587

@@ -1620,10 +1619,7 @@ struct http_pack_request *new_http_pack_request(
16201619
fprintf(stderr,
16211620
"Resuming fetch of pack %s at byte %ld\n",
16221621
sha1_to_hex(target->sha1), prev_posn);
1623-
xsnprintf(range, sizeof(range), "Range: bytes=%ld-", prev_posn);
1624-
preq->range_header = curl_slist_append(NULL, range);
1625-
curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
1626-
preq->range_header);
1622+
http_opt_request_remainder(preq->slot->curl, prev_posn);
16271623
}
16281624

16291625
return preq;
@@ -1673,8 +1669,6 @@ struct http_object_request *new_http_object_request(const char *base_url,
16731669
char prev_buf[PREV_BUF_SIZE];
16741670
ssize_t prev_read = 0;
16751671
long prev_posn = 0;
1676-
char range[RANGE_HEADER_SIZE];
1677-
struct curl_slist *range_header = NULL;
16781672
struct http_object_request *freq;
16791673

16801674
freq = xcalloc(1, sizeof(*freq));
@@ -1780,10 +1774,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
17801774
fprintf(stderr,
17811775
"Resuming fetch of object %s at byte %ld\n",
17821776
hex, prev_posn);
1783-
xsnprintf(range, sizeof(range), "Range: bytes=%ld-", prev_posn);
1784-
range_header = curl_slist_append(range_header, range);
1785-
curl_easy_setopt(freq->slot->curl,
1786-
CURLOPT_HTTPHEADER, range_header);
1777+
http_opt_request_remainder(freq->slot->curl, prev_posn);
17871778
}
17881779

17891780
return freq;

http.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ struct http_pack_request {
190190
struct packed_git **lst;
191191
FILE *packfile;
192192
char tmpfile[PATH_MAX];
193-
struct curl_slist *range_header;
194193
struct active_request_slot *slot;
195194
};
196195

0 commit comments

Comments
 (0)