Re: [PATCH 2/3] http: prefer CURLOPT_SEEKFUNCTION to CURLOPT_IOCTLFUNCTION

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 15/01/2023 20:10, Jeff King wrote:
> 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.

Ah, I didn't even think about this! I knew they were implemented in 7.18.0
and (as I mentioned previously) used the curl version number to switch
between the two sets of 'options'/implementations. Duh! :(

This is much better!

> 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@xxxxxxxx>
> ---
>  http-push.c   |  4 ++--
>  http.c        | 20 +++++++++-----------
>  http.h        |  2 +-
>  remote-curl.c | 28 +++++++++++++---------------
>  4 files changed, 25 insertions(+), 29 deletions(-)
> 
> diff --git a/http-push.c b/http-push.c
> index 1b18e775d0..7f71316456 100644
> --- a/http-push.c
> +++ b/http-push.c
> @@ -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 8a5ba3f477..ca0fe80ddb 100644
> --- a/http.c
> +++ b/http.c
> @@ -157,21 +157,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");

I didn't even think to check this; as you say, the documentation
claims only to send SEEK_SET, so ... (but this is obviously a
good idea).

> +	if (offset < 0 || offset >= buffer->buf.len) {
> +		error("curl seek would be outside of buffer");
> +		return CURL_SEEKFUNC_FAIL;
>  	}

I did at least do this! :)

> +
> +	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 3c94c47910..77c042706c 100644
> --- 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);
> diff --git a/remote-curl.c b/remote-curl.c
> index 72dfb8fb86..a76b6405eb 100644
> --- a/remote-curl.c
> +++ b/remote-curl.c
> @@ -717,25 +717,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 {
> @@ -959,8 +957,8 @@ static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_rece
>  		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);

It looks so much better without #ifdef's (or having to worry about
the git-curl-compat.h header file)!

LGTM

ATB,
Ramsay Jones




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux