[C-Api] type of ml-information handle
authorJaeyun Jung <jy1210.jung@samsung.com>
Tue, 8 Aug 2023 02:15:35 +0000 (11:15 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Fri, 18 Aug 2023 17:27:02 +0000 (02:27 +0900)
Prevent invalid function call.
Add type of ml-information handle and macro to check the handle.

Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
c/src/ml-api-common.c
c/src/ml-api-internal.h
tests/capi/unittest_capi_inference_single.cc

index e9bed4e..970df23 100644 (file)
 #include "ml-api-internal.h"
 
 /**
+ * @brief Enumeration for ml_info type.
+ */
+typedef enum
+{
+  ML_INFO_TYPE_UNKNOWN = 0,
+  ML_INFO_TYPE_OPTION = 0xfeed0001,
+  ML_INFO_TYPE_INFORMATION = 0xfeed0010,
+  ML_INFO_TYPE_INFORMATION_LIST = 0xfeed0011,
+
+  ML_INFO_TYPE_MAX = 0xfeedffff
+} ml_info_type_e;
+
+/**
+ * @brief Data structure for value of ml_info.
+ */
+typedef struct
+{
+  void *value; /**< The data given by user. */
+  ml_data_destroy_cb destroy; /**< The destroy func given by user. */
+} ml_info_value_s;
+
+/**
+ * @brief Data structure for ml_info.
+ */
+typedef struct
+{
+  ml_info_type_e type; /**< The type of ml_info. */
+  GHashTable *table; /**< hash table used by ml_info. */
+} ml_info_s;
+
+/**
+ * @brief Data structure for ml_info_list.
+ */
+typedef struct
+{
+  ml_info_type_e type; /**< The type of ml_info. */
+  unsigned int length; /**< The length of data. */
+  ml_info_s **info; /**< array of ml_info. */
+} ml_info_list_s;
+
+/**
  * @brief Gets the version number of machine-learning API.
  */
 void
@@ -1493,6 +1534,50 @@ ml_strerror (int errnum)
 }
 
 /**
+ * @brief Internal function to check the handle is valid.
+ */
+static bool
+_ml_info_is_valid (gpointer handle, ml_info_type_e expected)
+{
+  ml_info_type_e current;
+
+  if (!handle)
+    return false;
+
+  /* The first field should be an enum value of ml_info_type_e. */
+  current = *((ml_info_type_e *) handle);
+  if (current != expected)
+    return false;
+
+  switch (current) {
+    case ML_INFO_TYPE_OPTION:
+    case ML_INFO_TYPE_INFORMATION:
+    {
+      ml_info_s *_info = (ml_info_s *) handle;
+
+      if (!_info->table)
+        return false;
+
+      break;
+    }
+    case ML_INFO_TYPE_INFORMATION_LIST:
+    {
+      ml_info_list_s *_list = (ml_info_list_s *) handle;
+
+      if (_list->length == 0 || !_list->info)
+        return false;
+
+      break;
+    }
+    default:
+      /* Unknown type */
+      return false;
+  }
+
+  return true;
+}
+
+/**
  * @brief Internal function for destroy value of option table
  */
 static void
@@ -1546,8 +1631,12 @@ _ml_info_destroy (ml_info_s * info)
   if (!info)
     return;
 
-  if (info->table)
+  info->type = ML_INFO_TYPE_UNKNOWN;
+
+  if (info->table) {
     g_hash_table_destroy (info->table);
+    info->table = NULL;
+  }
 
   g_free (info);
   return;
@@ -1614,7 +1703,7 @@ ml_option_create (ml_option_h * option)
         "The parameter, 'option' is NULL. It should be a valid ml_option_h");
   }
 
-  _option = _ml_info_create (ML_INFO_OPTION);
+  _option = _ml_info_create (ML_INFO_TYPE_OPTION);
   if (_option == NULL)
     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
         "Failed to allocate memory for the option handle. Out of memory?");
@@ -1636,6 +1725,10 @@ ml_option_destroy (ml_option_h option)
         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
   }
 
+  if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'option' is not a ml-option handle.");
+
   _ml_info_destroy ((ml_info_s *) option);
 
   return ML_ERROR_NONE;
@@ -1672,6 +1765,10 @@ ml_option_set (ml_option_h option, const char *key, void *value,
         "The parameter, 'value' is NULL. It should be a valid void*");
   }
 
+  if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'option' is not a ml-option handle.");
+
   return _ml_info_set_value ((ml_info_s *) option, key, value, destroy);
 }
 
@@ -1698,6 +1795,10 @@ ml_option_get (ml_option_h option, const char *key, void **value)
         "The parameter, 'value' is NULL. It should be a valid void**");
   }
 
+  if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'option' is not a ml-option handle.");
+
   return _ml_info_get_value ((ml_info_s *) option, key, value);
 }
 
@@ -1716,7 +1817,7 @@ _ml_information_create (ml_information_h * info)
         "The parameter, 'info' is NULL. It should be a valid ml_information_h");
   }
 
-  _info = _ml_info_create (ML_INFO_MODEL);
+  _info = _ml_info_create (ML_INFO_TYPE_INFORMATION);
   if (!_info)
     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
         "Failed to allocate memory for the info handle. Out of memory?");
@@ -1750,6 +1851,10 @@ _ml_information_set (ml_information_h information, const char *key, void *value,
         "The parameter, 'value' is NULL. It should be a valid void*");
   }
 
+  if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'information' is not a ml-information handle.");
+
   return _ml_info_set_value ((ml_info_s *) information, key, value, destroy);
 }
 
@@ -1766,6 +1871,10 @@ ml_information_destroy (ml_information_h information)
         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
   }
 
+  if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'information' is not a ml-information handle.");
+
   _ml_info_destroy ((ml_info_s *) information);
 
   return ML_ERROR_NONE;
@@ -1794,6 +1903,10 @@ ml_information_get (ml_information_h information, const char *key, void **value)
         "The parameter, 'value' is NULL. It should be a valid void**");
   }
 
+  if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'information' is not a ml-information handle.");
+
   return _ml_info_get_value ((ml_info_s *) information, key, value);
 }
 
@@ -1808,6 +1921,8 @@ _ml_info_list_destroy (ml_info_list_s * list)
   if (!list)
     return;
 
+  list->type = ML_INFO_TYPE_UNKNOWN;
+
   for (i = 0; i < list->length; ++i) {
     _ml_info_destroy (list->info[i]);
   }
@@ -1865,10 +1980,11 @@ _ml_information_list_create (const unsigned int length,
   if (!_info_list->info)
     goto error;
 
+  _info_list->type = ML_INFO_TYPE_INFORMATION_LIST;
   _info_list->length = length;
 
   for (i = 0; i < length; i++) {
-    _info_list->info[i] = _ml_info_create (ML_INFO_MODEL);
+    _info_list->info[i] = _ml_info_create (ML_INFO_TYPE_INFORMATION);
     if (_info_list->info[i] == NULL)
       goto error;
   }
@@ -1895,6 +2011,10 @@ ml_information_list_destroy (ml_information_list_h list)
         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
   }
 
+  if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'list' is not a ml-information-list handle.");
+
   _ml_info_list_destroy ((ml_info_list_s *) list);
 
   return ML_ERROR_NONE;
@@ -1918,6 +2038,10 @@ ml_information_list_length (ml_information_list_h list, unsigned int *length)
         "The parameter, 'length' is NULL. It should be a valid unsigned int*");
   }
 
+  if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'list' is not a ml-information-list handle.");
+
   *length = _ml_info_list_length ((ml_info_list_s *) list);
 
   return ML_ERROR_NONE;
@@ -1943,6 +2067,10 @@ ml_information_list_get (ml_information_list_h list, unsigned int index,
         "The parameter, 'information' is NULL. It should be a valid ml_information_h*");
   }
 
+  if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST))
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, 'list' is not a ml-information-list handle.");
+
   info_s = _ml_info_list_get ((ml_info_list_s *) list, index);
   if (info_s == NULL) {
     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
index df7b0db..ca92495 100644 (file)
@@ -168,43 +168,6 @@ typedef struct {
 } ml_tensors_info_s;
 
 /**
- * @brief Enumeration for ml_info.
- */
-typedef enum {
-  ML_INFO_OPTION = 0,
-  ML_INFO_MODEL,
-
-  ML_INFO_MAX
-} ml_info_type_e;
-
-/**
- * @brief Data structure for value of ml_info.
- */
-typedef struct
-{
-  void *value; /**< The data given by user. */
-  ml_data_destroy_cb destroy; /**< The destroy func given by user. */
-} ml_info_value_s;
-
-/**
- * @brief Data structure for ml_info.
- */
-typedef struct
-{
-  ml_info_type_e type; /**< The type of ml_info. */
-  GHashTable *table; /**< hash table used by ml_info. */
-} ml_info_s;
-
-/**
- * @brief Data structure for ml_info_list.
- */
-typedef struct
-{
-  unsigned int length; /**< The length of data. */
-  ml_info_s **info; /**< array of ml_info. */
-} ml_info_list_s;
-
-/**
  * @brief Macro to control private lock with nolock condition (lock)
  * @param sname The name of struct (ml_tensors_info_s or ml_tensors_data_s)
  */
index f729983..bf7360d 100644 (file)
@@ -3955,6 +3955,88 @@ TEST (nnstreamer_capi_ml_option, test04_n)
 }
 
 /**
+ * @brief Test ml_option with invalid type.
+ */
+TEST (nnstreamer_capi_ml_information, invalidHandle01_n)
+{
+  int status;
+  ml_information_h info;
+  void *value;
+  void *test_val = g_malloc0 (sizeof (int));
+
+  status = _ml_information_create (&info);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  status = ml_option_set (info, "temp-key", test_val, NULL);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_option_get (info, "temp-key", &value);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_option_destroy (info);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_information_destroy (info);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  g_free (test_val);
+}
+
+/**
+ * @brief Test ml_information with invalid type.
+ */
+TEST (nnstreamer_capi_ml_information, invalidHandle02_n)
+{
+  int status;
+  ml_option_h option;
+  void *value;
+  void *test_val = g_malloc0 (sizeof (int));
+
+  status = ml_option_create (&option);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  status = _ml_information_set (option, "temp-key", test_val, NULL);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_information_get (option, "temp-key", &value);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_information_destroy (option);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_option_destroy (option);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  g_free (test_val);
+}
+
+/**
+ * @brief Test ml_information_list with invalid type.
+ */
+TEST (nnstreamer_capi_ml_information, invalidHandle03_n)
+{
+  int status;
+  ml_option_h info_list;
+  ml_information_h info;
+  unsigned int len;
+
+  status = ml_option_create (&info_list);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  status = ml_information_list_length (info_list, &len);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_information_list_get (info_list, 0U, &info);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_information_list_destroy (info_list);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  status = ml_option_destroy (info_list);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+}
+
+/**
  * @brief Test ml_option with tensorflow-lite
  */
 TEST (nnstreamer_capi_ml_option, tensorflow_lite)