]> git.ipfire.org Git - thirdparty/git.git/commitdiff
http: prefer CURLOPT_SEEKFUNCTION to CURLOPT_IOCTLFUNCTION
authorJeff King <peff@peff.net>
Tue, 17 Jan 2023 03:04:44 +0000 (22:04 -0500)
committerJohannes Schindelin <johannes.schindelin@gmx.de>
Mon, 6 Feb 2023 08:27:09 +0000 (09:27 +0100)
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>
INSTALL
http-push.c
http.c
http.h
remote-curl.c

diff --git a/INSTALL b/INSTALL
index 4140a3f5c8b6946ca821c2a876cd4390a1a05f1b..8dd577e1020bcca6351abde0d876cc2dfa11493c 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -144,7 +144,7 @@ Issues of note:
          not need that functionality, use NO_CURL to build without
          it.
 
-         Git requires version "7.19.4" or later of "libcurl" to build
+         Git requires version "7.19.5" or later of "libcurl" to build
          without NO_CURL. This version requirement may be bumped in
          the future.
 
index 331af5ffcb2e2d0ef9dfaba9b6f297fed53fdca9..b4aeae9e2695369c648ba615e182ab5c3f08561b 100644 (file)
@@ -203,8 +203,8 @@ static void curl_setup_http(CURL *curl, const char *url,
        curl_easy_setopt(curl, CURLOPT_INFILE, buffer);
        curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
-       curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
-       curl_easy_setopt(curl, CURLOPT_IOCTLDATA, buffer);
+       curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer);
+       curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
        curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req);
diff --git a/http.c b/http.c
index f92859f43fa53e0352b239ca43a769c5f9ff4aae..31ccc99a44cfc3962126273782b17387f787f796 100644 (file)
--- a/http.c
+++ b/http.c
@@ -155,21 +155,19 @@ size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
        return size / eltsize;
 }
 
-curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
+int seek_buffer(void *clientp, curl_off_t offset, int origin)
 {
        struct buffer *buffer = clientp;
 
-       switch (cmd) {
-       case CURLIOCMD_NOP:
-               return CURLIOE_OK;
-
-       case CURLIOCMD_RESTARTREAD:
-               buffer->posn = 0;
-               return CURLIOE_OK;
-
-       default:
-               return CURLIOE_UNKNOWNCMD;
+       if (origin != SEEK_SET)
+               BUG("seek_buffer only handles SEEK_SET");
+       if (offset < 0 || offset >= buffer->buf.len) {
+               error("curl seek would be outside of buffer");
+               return CURL_SEEKFUNC_FAIL;
        }
+
+       buffer->posn = offset;
+       return CURL_SEEKFUNC_OK;
 }
 
 size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
diff --git a/http.h b/http.h
index df1590e53a455787a2d4d28a7896cabf8ac15419..77e0520582dfc94af8d0eeb875355e6dfb09b524 100644 (file)
--- a/http.h
+++ b/http.h
@@ -40,7 +40,7 @@ struct buffer {
 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_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
-curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
+int seek_buffer(void *clientp, curl_off_t offset, int origin);
 
 /* Slot lifecycle functions */
 struct active_request_slot *get_active_slot(void);
index d69156312bda65c7f081a0bfd8c91b043f676487..1b5d9ac1d82d93c8ca0c20c89d5a74024278a661 100644 (file)
@@ -710,25 +710,23 @@ static size_t rpc_out(void *ptr, size_t eltsize,
        return avail;
 }
 
-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;
 
-       switch (cmd) {
-       case CURLIOCMD_NOP:
-               return CURLIOE_OK;
+       if (origin != SEEK_SET)
+               BUG("rpc_seek only handles SEEK_SET, not %d", origin);
 
-       case CURLIOCMD_RESTARTREAD:
-               if (rpc->initial_buffer) {
-                       rpc->pos = 0;
-                       return CURLIOE_OK;
+       if (rpc->initial_buffer) {
+               if (offset < 0 || offset > rpc->len) {
+                       error("curl seek would be outside of rpc buffer");
+                       return CURL_SEEKFUNC_FAIL;
                }
-               error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
-               return CURLIOE_FAILRESTART;
-
-       default:
-               return CURLIOE_UNKNOWNCMD;
+               rpc->pos = offset;
+               return CURL_SEEKFUNC_OK;
        }
+       error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
+       return CURL_SEEKFUNC_FAIL;
 }
 
 struct check_pktline_state {
@@ -948,8 +946,8 @@ retry:
                rpc->initial_buffer = 1;
                curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
                curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc);
-               curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, rpc_ioctl);
-               curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, rpc);
+               curl_easy_setopt(slot->curl, CURLOPT_SEEKFUNCTION, rpc_seek);
+               curl_easy_setopt(slot->curl, CURLOPT_SEEKDATA, rpc);
                if (options.verbosity > 1) {
                        fprintf(stderr, "POST %s (chunked)\n", rpc->service_name);
                        fflush(stderr);