http: prefer CURLOPT_SEEKFUNCTION to CURLOPT_IOCTLFUNCTION
The IOCTLFUNCTION option has been deprecated, and generates a compiler warning in recent versions of curl. We can switch to using SEEKFUNCTION instead. It was added in 2008 via curl 7.18.0; our INSTALL file already indicates we require at least curl 7.19.4. But there's one catch: curl says we should use CURL_SEEKFUNC_{OK,FAIL}, and those didn't arrive until 7.19.5. One workaround would be to use a bare 0/1 here (or define our own macros). But let's just bump the minimum required version to 7.19.5. That version is only a minor version bump from our existing requirement, and is only a 2 month time bump for versions that are almost 13 years old. So it's not likely that anybody cares about the distinction. Switching means we have to rewrite the ioctl functions into seek functions. In some ways they are simpler (seeking is the only operation), but in some ways more complex (the ioctl allowed only a full rewind, but now we can seek to arbitrary offsets). Curl will only ever use SEEK_SET (per their documentation), so I didn't bother implementing anything else, since it would naturally be completely untested. This seems unlikely to change, but I added an assertion just in case. Likewise, I doubt curl will ever try to seek outside of the buffer sizes we've told it, but I erred on the defensive side here, rather than do an out-of-bounds read. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
parent
fda237cb64
commit
b0e3e2d06b
4
INSTALL
4
INSTALL
@ -145,6 +145,10 @@ Issues of note:
|
|||||||
patches into an IMAP mailbox, you do not have to have them
|
patches into an IMAP mailbox, you do not have to have them
|
||||||
(use NO_CURL).
|
(use NO_CURL).
|
||||||
|
|
||||||
|
Git requires version "7.19.5" or later of "libcurl" to build
|
||||||
|
without NO_CURL. This version requirement may be bumped in
|
||||||
|
the future.
|
||||||
|
|
||||||
- "expat" library; git-http-push uses it for remote lock
|
- "expat" library; git-http-push uses it for remote lock
|
||||||
management over DAV. Similar to "curl" above, this is optional
|
management over DAV. Similar to "curl" above, this is optional
|
||||||
(with NO_EXPAT).
|
(with NO_EXPAT).
|
||||||
|
@ -203,9 +203,9 @@ static void curl_setup_http(CURL *curl, const char *url,
|
|||||||
curl_easy_setopt(curl, CURLOPT_INFILE, buffer);
|
curl_easy_setopt(curl, CURLOPT_INFILE, buffer);
|
||||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len);
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len);
|
||||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
|
curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer);
|
||||||
curl_easy_setopt(curl, CURLOPT_IOCTLDATA, buffer);
|
curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer);
|
||||||
#endif
|
#endif
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
|
||||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
|
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
|
||||||
|
22
http.c
22
http.c
@ -186,22 +186,20 @@ size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
|
|||||||
return size / eltsize;
|
return size / eltsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
|
int seek_buffer(void *clientp, curl_off_t offset, int origin)
|
||||||
{
|
{
|
||||||
struct buffer *buffer = clientp;
|
struct buffer *buffer = clientp;
|
||||||
|
|
||||||
switch (cmd) {
|
if (origin != SEEK_SET)
|
||||||
case CURLIOCMD_NOP:
|
BUG("seek_buffer only handles SEEK_SET");
|
||||||
return CURLIOE_OK;
|
if (offset < 0 || offset >= buffer->buf.len) {
|
||||||
|
error("curl seek would be outside of buffer");
|
||||||
case CURLIOCMD_RESTARTREAD:
|
return CURL_SEEKFUNC_FAIL;
|
||||||
buffer->posn = 0;
|
|
||||||
return CURLIOE_OK;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return CURLIOE_UNKNOWNCMD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer->posn = offset;
|
||||||
|
return CURL_SEEKFUNC_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
8
http.h
8
http.h
@ -41,8 +41,8 @@
|
|||||||
#define CURLE_HTTP_RETURNED_ERROR CURLE_HTTP_NOT_FOUND
|
#define CURLE_HTTP_RETURNED_ERROR CURLE_HTTP_NOT_FOUND
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LIBCURL_VERSION_NUM < 0x070c03
|
#if LIBCURL_VERSION_NUM < 0x071200
|
||||||
#define NO_CURL_IOCTL
|
#define NO_CURL_SEEK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -82,8 +82,8 @@ struct buffer {
|
|||||||
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||||
size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||||
size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
|
int seek_buffer(void *clientp, curl_off_t offset, int origin);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Slot lifecycle functions */
|
/* Slot lifecycle functions */
|
||||||
|
@ -707,26 +707,24 @@ static size_t rpc_out(void *ptr, size_t eltsize,
|
|||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
|
static int rpc_seek(void *clientp, curl_off_t offset, int origin)
|
||||||
{
|
{
|
||||||
struct rpc_state *rpc = clientp;
|
struct rpc_state *rpc = clientp;
|
||||||
|
|
||||||
switch (cmd) {
|
if (origin != SEEK_SET)
|
||||||
case CURLIOCMD_NOP:
|
BUG("rpc_seek only handles SEEK_SET, not %d", origin);
|
||||||
return CURLIOE_OK;
|
|
||||||
|
|
||||||
case CURLIOCMD_RESTARTREAD:
|
|
||||||
if (rpc->initial_buffer) {
|
if (rpc->initial_buffer) {
|
||||||
rpc->pos = 0;
|
if (offset < 0 || offset > rpc->len) {
|
||||||
return CURLIOE_OK;
|
error("curl seek would be outside of rpc buffer");
|
||||||
|
return CURL_SEEKFUNC_FAIL;
|
||||||
|
}
|
||||||
|
rpc->pos = offset;
|
||||||
|
return CURL_SEEKFUNC_OK;
|
||||||
}
|
}
|
||||||
error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
|
error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
|
||||||
return CURLIOE_FAILRESTART;
|
return CURL_SEEKFUNC_FAIL;
|
||||||
|
|
||||||
default:
|
|
||||||
return CURLIOE_UNKNOWNCMD;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -947,9 +945,9 @@ retry:
|
|||||||
rpc->initial_buffer = 1;
|
rpc->initial_buffer = 1;
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
|
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc);
|
curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc);
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, rpc_ioctl);
|
curl_easy_setopt(slot->curl, CURLOPT_SEEKFUNCTION, rpc_seek);
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, rpc);
|
curl_easy_setopt(slot->curl, CURLOPT_SEEKDATA, rpc);
|
||||||
#endif
|
#endif
|
||||||
if (options.verbosity > 1) {
|
if (options.verbosity > 1) {
|
||||||
fprintf(stderr, "POST %s (chunked)\n", rpc->service_name);
|
fprintf(stderr, "POST %s (chunked)\n", rpc->service_name);
|
||||||
|
Loading…
Reference in New Issue
Block a user