On Sat, Sep 07, 2024 at 17:15:21 +0300, Nikolai Barybin via Devel wrote:
> Signed-off-by: Nikolai Barybin <[email protected]>
> ---
> src/storage_file/storage_file_probe.c | 53 +++++++++++++++++++++++++--
> 1 file changed, 49 insertions(+), 4 deletions(-)
>
> diff --git a/src/storage_file/storage_file_probe.c
> b/src/storage_file/storage_file_probe.c
> index 4792b9fdff..21430d18aa 100644
> --- a/src/storage_file/storage_file_probe.c
> +++ b/src/storage_file/storage_file_probe.c
> @@ -106,6 +106,7 @@ qcow2GetClusterSize(const char *buf,
> size_t buf_size);
> static int qcowXGetBackingStore(char **, int *,
> const char *, size_t);
> +static int qcowXGetDataFile(char **, char *, int, size_t);
data file is a qcow2 only feature so calling this 'qcowX' makes no sense
as it won't be reused.
> static int qcow2GetFeatures(virBitmap **features, int format,
> char *buf, ssize_t len);
> static int vmdk4GetBackingStore(char **, int *,
> @@ -393,7 +395,8 @@ cowGetBackingStore(char **res,
> static int
> qcow2GetExtensions(const char *buf,
> size_t buf_size,
> - int *backingFormat)
> + int *backingFormat,
> + char **dataFilePath)
> {
> size_t offset;
> size_t extension_start;
> @@ -488,6 +491,17 @@ qcow2GetExtensions(const char *buf,
> break;
> }
>
> + case QCOW2_HDR_EXTENSION_DATA_FILE_NAME: {
> + g_autofree char *tmp = NULL;
'tmp' is unused.
> + if (!dataFilePath)
> + break;
> +
> + *(char **)dataFilePath = g_new0(char, len + 1);
No need for that amount of typecasts since 'dataFilePath' is aready 'char
**'
> + memcpy(*(char **)dataFilePath, buf + offset, len);
same here.
> + (*((char **)dataFilePath))[len] = '\0';
This is not needed as g_new0 allocates a zeroed-out buffer.
> + break;
> + }
> +
> case QCOW2_HDR_EXTENSION_END:
> return 0;
> }
> @@ -554,9 +568,34 @@ qcowXGetBackingStore(char **res,
> memcpy(*res, buf + offset, size);
> (*res)[size] = '\0';
>
> - if (qcow2GetExtensions(buf, buf_size, format) < 0)
> + if (qcow2GetExtensions(buf, buf_size, format, NULL) < 0)
> + return 0;
> +
> + return 0;
> +}
> +
> +
> +static int
> +qcowXGetDataFile(char **res,
> + char *buf,
> + int format,
> + size_t buf_size)
> +{
> + virBitmap *features = NULL;
> + char *filename = NULL;
> + *res = NULL;
> +
> + if (buf_size < QCOW2v3_HDR_FEATURES_INCOMPATIBLE + 8)
> return 0;
>
> + ignore_value(qcow2GetFeatures(&features, format, buf, buf_size));
'qcowXGetDataFile' gets called one block before 'qcow2GetFeatures' would
be called via
'fileTypeInfo[meta->format].getFeatures(&meta->features,'
but here you do it again. Restrucutre the code so that iut doesn't need
to do this twice.
> + if (features && virBitmapIsBitSet(features,
> VIR_STORAGE_FILE_FEATURE_DATA_FILE)) {
> + if (qcow2GetExtensions(buf, buf_size, NULL, &filename) < 0)
So 'filename' will be filled with an allocated buffer ...
> + return 0;
> +
> + *res = g_strdup(filename);
... you'll dup it (which is wasteful) and then leak the original.
> + }
> +
> return 0;
> }
>
> @@ -963,6 +1002,12 @@ virStorageFileProbeGetMetadata(virStorageSource *meta,
> meta->backingStoreRawFormat = format;
> }
>
> + VIR_FREE(meta->dataFileRaw);
> + if (fileTypeInfo[meta->format].getDataFile != NULL) {
> + fileTypeInfo[meta->format].getDataFile(&meta->dataFileRaw,
> + buf, meta->format, len);
> + }
> +
> g_clear_pointer(&meta->features, virBitmapFree);
> if (fileTypeInfo[meta->format].getFeatures != NULL &&
> fileTypeInfo[meta->format].getFeatures(&meta->features,
> meta->format, buf, len) < 0)
> --
> 2.43.5
>