From 9598ddeb3dff4e51a9989067e912baf502410cee Mon Sep 17 00:00:00 2001
From: Heiko Lewin <hlewin@worldiety.de>
Date: Sun, 10 Mar 2024 13:32:18 +0100
Subject: [PATCH] encoder_kvazaar.cc: Fix some memory leaks

---
 libheif/plugins/encoder_kvazaar.cc | 50 +++++++++++++-----------------
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/libheif/plugins/encoder_kvazaar.cc b/libheif/plugins/encoder_kvazaar.cc
index eada77f9fe..158f174b04 100644
--- a/libheif/plugins/encoder_kvazaar.cc
+++ b/libheif/plugins/encoder_kvazaar.cc
@@ -361,6 +361,11 @@ static void copy_plane(kvz_pixel* out_p,
 }


+template<typename T, typename D>
+std::unique_ptr<T, D> make_guard(T* ptr, D&& deleter) {
+    return std::unique_ptr<T, D>(ptr, deleter);
+}
+
 static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct heif_image* image,
                                               heif_image_input_class input_class)
 {
@@ -380,7 +385,8 @@ static struct heif_error kvazaar_encode_
     return err;
   }

-  kvz_config* config = api->config_alloc();
+  auto uconfig = make_guard(api->config_alloc(), [api](kvz_config* cfg) { api->config_destroy(cfg); });
+  kvz_config* config = uconfig.get();
   api->config_init(config); // param, encoder->preset.c_str(), encoder->tune.c_str());
 #if HAVE_KVAZAAR_ENABLE_LOGGING
   config->enable_logging_output = 0;
@@ -541,9 +547,9 @@ static struct heif_error kvazaar_encode_
   }
 */

-  kvz_picture* pic = api->picture_alloc_csp(kvzChroma, encoded_width, encoded_height);
+  auto upic = make_guard(api->picture_alloc_csp(kvzChroma, encoded_width, encoded_height), [api](kvz_picture* pic) { api->picture_free(pic); });
+  kvz_picture* pic = upic.get();
   if (!pic) {
-    api->config_destroy(config);
     return heif_error{
         heif_error_Encoder_plugin_error,
         heif_suberror_Encoder_encoding,
@@ -573,11 +579,9 @@ static struct heif_error kvazaar_encode_
                encoded_width >> chroma_stride_shift, encoded_height >> chroma_height_shift);
   }

-  kvz_encoder* kvzencoder = api->encoder_open(config);
+  auto uencoder = make_guard(api->encoder_open(config), [api](kvz_encoder* e) { api->encoder_close(e); });
+  kvz_encoder* kvzencoder = uencoder.get();
   if (!kvzencoder) {
-    api->picture_free(pic);
-    api->config_destroy(config);
-
     return heif_error{
         heif_error_Encoder_plugin_error,
         heif_suberror_Encoder_encoding,
@@ -586,14 +590,18 @@ static struct heif_error kvazaar_encode_
   }

   kvz_data_chunk* data = nullptr;
+  auto free_data = [api](kvz_data_chunk** data){
+    if(*data) {
+        api->chunk_free(*data);
+        *data = nullptr;
+    }
+  };
+  auto data_deleter = std::unique_ptr<kvz_data_chunk*, decltype(free_data)>(&data, free_data);
+
   uint32_t data_len;
   int success;
   success = api->encoder_headers(kvzencoder, &data, &data_len);
   if (!success) {
-    api->picture_free(pic);
-    api->config_destroy(config);
-    api->encoder_close(kvzencoder);
-
     return heif_error{
         heif_error_Encoder_plugin_error,
         heif_suberror_Encoder_encoding,
@@ -602,17 +610,13 @@ static struct heif_error kvazaar_encode_
   }

   append_chunk_data(data, encoder->output_data);
+  free_data(&data);

   success = api->encoder_encode(kvzencoder,
                                 pic,
                                 &data, &data_len,
                                 nullptr, nullptr, nullptr);
   if (!success) {
-    api->chunk_free(data);
-    api->picture_free(pic);
-    api->config_destroy(config);
-    api->encoder_close(kvzencoder);
-
     return heif_error{
         heif_error_Encoder_plugin_error,
         heif_suberror_Encoder_encoding,
@@ -621,6 +625,7 @@ static struct heif_error kvazaar_encode_
   }

   append_chunk_data(data, encoder->output_data);
+  free_data(&data);

   for (;;) {
     success = api->encoder_encode(kvzencoder,
@@ -628,11 +633,6 @@ static struct heif_error kvazaar_encode_
                                   &data, &data_len,
                                   nullptr, nullptr, nullptr);
     if (!success) {
-      api->chunk_free(data);
-      api->picture_free(pic);
-      api->config_destroy(config);
-      api->encoder_close(kvzencoder);
-
       return heif_error{
           heif_error_Encoder_plugin_error,
           heif_suberror_Encoder_encoding,
@@ -645,16 +645,10 @@ static struct heif_error kvazaar_encode_
     }

     append_chunk_data(data, encoder->output_data);
+    free_data(&data);
   }

   (void) success;
-
-  api->chunk_free(data);
-
-  api->encoder_close(kvzencoder);
-  api->picture_free(pic);
-  api->config_destroy(config);
-
   return heif_error_ok;
 }