[libvirt] [PATCH v2] esx: Extend esxVI_CURL_Download for partial downloads

Doug Goldstein cardoe at gentoo.org
Sun Jul 8 19:09:32 UTC 2012


On Sun, Jul 8, 2012 at 5:44 AM, Matthias Bolte
<matthias.bolte at googlemail.com> wrote:
> Also ensure that the virBuffer used to store the downloaded data
> does not overflow.
> ---
>
> v2:
>  - Ensure that the used virBuffer dos not overflow.
>
>  src/esx/esx_driver.c |    2 +-
>  src/esx/esx_vi.c     |   62 +++++++++++++++++++++++++++++++++++++++++++------
>  src/esx/esx_vi.h     |    3 +-
>  3 files changed, 57 insertions(+), 10 deletions(-)
>
> diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
> index db2144c..95b9286 100644
> --- a/src/esx/esx_driver.c
> +++ b/src/esx/esx_driver.c
> @@ -2802,7 +2802,7 @@ esxDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
>
>      url = virBufferContentAndReset(&buffer);
>
> -    if (esxVI_CURL_Download(priv->primary->curl, url, &vmx) < 0) {
> +    if (esxVI_CURL_Download(priv->primary->curl, url, &vmx, 0, NULL) < 0) {
>          goto cleanup;
>      }
>
> diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
> index 48718b6..0769e8b 100644
> --- a/src/esx/esx_vi.c
> +++ b/src/esx/esx_vi.c
> @@ -116,9 +116,9 @@ ESX_VI__TEMPLATE__FREE(CURL,
>  })
>
>  static size_t
> -esxVI_CURL_ReadString(char *data, size_t size, size_t nmemb, void *ptrptr)
> +esxVI_CURL_ReadString(char *data, size_t size, size_t nmemb, void *userdata)
>  {
> -    const char *content = *(const char **)ptrptr;
> +    const char *content = *(const char **)userdata;
>      size_t available = 0;
>      size_t requested = size * nmemb;
>
> @@ -138,16 +138,28 @@ esxVI_CURL_ReadString(char *data, size_t size, size_t nmemb, void *ptrptr)
>
>      memcpy(data, content, requested);
>
> -    *(const char **)ptrptr = content + requested;
> +    *(const char **)userdata = content + requested;
>
>      return requested;
>  }
>
>  static size_t
> -esxVI_CURL_WriteBuffer(char *data, size_t size, size_t nmemb, void *buffer)
> +esxVI_CURL_WriteBuffer(char *data, size_t size, size_t nmemb, void *userdata)
>  {
> +    virBufferPtr buffer = userdata;
> +
>      if (buffer != NULL) {
> -        virBufferAdd((virBufferPtr) buffer, data, size * nmemb);
> +        /*
> +         * Using a virBuffer to store the download data limits the downloadable
> +         * size. This is no problem as esxVI_CURL_Download and esxVI_CURL_Perform
> +         * are meant to download small things such as VMX files, VMDK metadata
> +         * files and SOAP responses.
> +         */
> +        if (virBufferUse(buffer) > UINT32_MAX / 2) {
> +            return 0;
> +        }

This could never be true since the type would have already resulted in
an overflow and therefore would be less than UINT32_MAX / 2 (which is
equivalent to INT32_MAX).  Something like the below would ensure that
you are always within the bounds of your type :

if ((size * nmemb) <= (INT32_MAX - virBufferUse(buffer)) {
   virBufferAdd(...)
   return size * nmemb;
}

> +
> +        virBufferAdd(buffer, data, size * nmemb);
>
>          return size * nmemb;
>      }
> @@ -160,7 +172,7 @@ esxVI_CURL_WriteBuffer(char *data, size_t size, size_t nmemb, void *buffer)
>  #if ESX_VI__CURL__ENABLE_DEBUG_OUTPUT
>  static int
>  esxVI_CURL_Debug(CURL *curl ATTRIBUTE_UNUSED, curl_infotype type,
> -                 char *info, size_t size, void *data ATTRIBUTE_UNUSED)
> +                 char *info, size_t size, void *userdata ATTRIBUTE_UNUSED)
>  {
>      char *buffer = NULL;
>
> @@ -355,8 +367,10 @@ esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri)
>  }
>
>  int
> -esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content)
> +esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content,
> +                    unsigned long long offset, unsigned long long *length)
>  {
> +    char *range = NULL;
>      virBuffer buffer = VIR_BUFFER_INITIALIZER;
>      int responseCode = 0;
>
> @@ -365,9 +379,33 @@ esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content)
>          return -1;
>      }
>
> +    if (length != NULL && *length > 0) {
> +        /*
> +         * Using a virBuffer to store the download data limits the downloadable
> +         * size. This is no problem as esxVI_CURL_Download is meant to download
> +         * small things such as VMX of VMDK metadata files.
> +         */
> +        if (*length > UINT32_MAX / 2) {

Use INT32_MAX

> +            ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> +                         _("Download length it too large"));
> +            return -1;
> +        }
> +
> +        if (virAsprintf(&range, "%llu-%llu", offset, offset + *length - 1) < 0) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +    } else if (offset > 0) {
> +        if (virAsprintf(&range, "%llu-", offset) < 0) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +    }
> +
>      virMutexLock(&curl->lock);
>
>      curl_easy_setopt(curl->handle, CURLOPT_URL, url);
> +    curl_easy_setopt(curl->handle, CURLOPT_RANGE, range);
>      curl_easy_setopt(curl->handle, CURLOPT_WRITEDATA, &buffer);
>      curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 0);
>      curl_easy_setopt(curl->handle, CURLOPT_HTTPGET, 1);
> @@ -378,7 +416,7 @@ esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content)
>
>      if (responseCode < 0) {
>          goto cleanup;
> -    } else if (responseCode != 200) {
> +    } else if (responseCode != 200 && responseCode != 206) {
>          ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
>                       _("HTTP response code %d for download from '%s'"),
>                       responseCode, url);
> @@ -390,9 +428,15 @@ esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content)
>          goto cleanup;
>      }
>
> +    if (length != NULL) {
> +        *length = virBufferUse(&buffer);
> +    }
> +
>      *content = virBufferContentAndReset(&buffer);
>
>    cleanup:
> +    VIR_FREE(range);
> +
>      if (*content == NULL) {
>          virBufferFreeAndReset(&buffer);
>          return -1;
> @@ -414,6 +458,7 @@ esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content)
>      virMutexLock(&curl->lock);
>
>      curl_easy_setopt(curl->handle, CURLOPT_URL, url);
> +    curl_easy_setopt(curl->handle, CURLOPT_RANGE, NULL);
>      curl_easy_setopt(curl->handle, CURLOPT_READDATA, &content);
>      curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 1);
>      curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, strlen(content));
> @@ -1231,6 +1276,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
>      virMutexLock(&ctx->curl->lock);
>
>      curl_easy_setopt(ctx->curl->handle, CURLOPT_URL, ctx->url);
> +    curl_easy_setopt(ctx->curl->handle, CURLOPT_RANGE, NULL);
>      curl_easy_setopt(ctx->curl->handle, CURLOPT_WRITEDATA, &buffer);
>      curl_easy_setopt(ctx->curl->handle, CURLOPT_UPLOAD, 0);
>      curl_easy_setopt(ctx->curl->handle, CURLOPT_POSTFIELDS, request);
> diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
> index 9560bd2..49b7ca2 100644
> --- a/src/esx/esx_vi.h
> +++ b/src/esx/esx_vi.h
> @@ -167,7 +167,8 @@ struct _esxVI_CURL {
>  int esxVI_CURL_Alloc(esxVI_CURL **curl);
>  void esxVI_CURL_Free(esxVI_CURL **curl);
>  int esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri);
> -int esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content);
> +int esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content,
> +                        unsigned long long offset, unsigned long long *length);
>  int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content);
>
>
> --
> 1.7.4.1

Just a 2 nits mentioned above.

-- 
Doug Goldstein




More information about the libvir-list mailing list