Avoid VLAs with size depending on user input
authorPino Toscano <ptoscano@redhat.com>
Thu, 30 Aug 2018 10:13:41 +0000 (12:13 +0200)
committerRichard W.M. Jones <rjones@redhat.com>
Thu, 30 Aug 2018 10:26:32 +0000 (11:26 +0100)
Do not use var-length arrays with sizes from user input (like
parameters), since they may grow the stack too much.

Instead, allocate the memory on the heap.

libvirt/generator.pl
libvirt/libvirt_c.c
libvirt/libvirt_c_oneoffs.c

index 34801ba..ea1b2be 100755 (executable)
@@ -481,7 +481,7 @@ sub gen_c_code
   CAMLlocal1 (rv);
   virConnectPtr conn = Connect_val (connv);
   int i = Int_val (iv);
-  int ids[i], r;
+  int *ids, r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
    * so catch that and return an empty array directly.  This changes
@@ -493,12 +493,17 @@ sub gen_c_code
     CAMLreturn (rv);
   }
 
+  ids = malloc (sizeof (*ids) * i);
+  if (ids == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = $c_name (conn, ids, i));
-  CHECK_ERROR (r == -1, \"$c_name\");
+  CHECK_ERROR_CLEANUP (r == -1, free (ids), \"$c_name\");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i)
     Store_field (rv, i, Val_int (ids[i]));
+  free (ids);
 
   CAMLreturn (rv);
 "
@@ -507,7 +512,7 @@ sub gen_c_code
   CAMLlocal2 (rv, strv);
   " . gen_unpack_args ($1) . "
   int i = Int_val (iv);
-  char *names[i];
+  char **names;
   int r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
@@ -520,8 +525,12 @@ sub gen_c_code
     CAMLreturn (rv);
   }
 
+  names = malloc (sizeof (*names) * i);
+  if (names == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = $c_name ($1, names, i));
-  CHECK_ERROR (r == -1, \"$c_name\");
+  CHECK_ERROR_CLEANUP (r == -1, free (names), \"$c_name\");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i) {
@@ -529,6 +538,7 @@ sub gen_c_code
     Store_field (rv, i, strv);
     free (names[i]);
   }
+  free (names);
 
   CAMLreturn (rv);
 "
index 8d51944..0e731a8 100644 (file)
@@ -161,7 +161,7 @@ ocaml_libvirt_connect_list_domains (value connv, value iv)
   CAMLlocal1 (rv);
   virConnectPtr conn = Connect_val (connv);
   int i = Int_val (iv);
-  int ids[i], r;
+  int *ids, r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
    * so catch that and return an empty array directly.  This changes
@@ -173,12 +173,17 @@ ocaml_libvirt_connect_list_domains (value connv, value iv)
     CAMLreturn (rv);
   }
 
+  ids = malloc (sizeof (*ids) * i);
+  if (ids == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = virConnectListDomains (conn, ids, i));
-  CHECK_ERROR (r == -1, "virConnectListDomains");
+  CHECK_ERROR_CLEANUP (r == -1, free (ids), "virConnectListDomains");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i)
     Store_field (rv, i, Val_int (ids[i]));
+  free (ids);
 
   CAMLreturn (rv);
 }
@@ -213,7 +218,7 @@ ocaml_libvirt_connect_list_defined_domains (value connv, value iv)
   CAMLlocal2 (rv, strv);
   virConnectPtr conn = Connect_val (connv);
   int i = Int_val (iv);
-  char *names[i];
+  char **names;
   int r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
@@ -226,8 +231,12 @@ ocaml_libvirt_connect_list_defined_domains (value connv, value iv)
     CAMLreturn (rv);
   }
 
+  names = malloc (sizeof (*names) * i);
+  if (names == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = virConnectListDefinedDomains (conn, names, i));
-  CHECK_ERROR (r == -1, "virConnectListDefinedDomains");
+  CHECK_ERROR_CLEANUP (r == -1, free (names), "virConnectListDefinedDomains");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i) {
@@ -235,6 +244,7 @@ ocaml_libvirt_connect_list_defined_domains (value connv, value iv)
     Store_field (rv, i, strv);
     free (names[i]);
   }
+  free (names);
 
   CAMLreturn (rv);
 }
@@ -269,7 +279,7 @@ ocaml_libvirt_connect_list_networks (value connv, value iv)
   CAMLlocal2 (rv, strv);
   virConnectPtr conn = Connect_val (connv);
   int i = Int_val (iv);
-  char *names[i];
+  char **names;
   int r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
@@ -282,8 +292,12 @@ ocaml_libvirt_connect_list_networks (value connv, value iv)
     CAMLreturn (rv);
   }
 
+  names = malloc (sizeof (*names) * i);
+  if (names == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = virConnectListNetworks (conn, names, i));
-  CHECK_ERROR (r == -1, "virConnectListNetworks");
+  CHECK_ERROR_CLEANUP (r == -1, free (names), "virConnectListNetworks");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i) {
@@ -291,6 +305,7 @@ ocaml_libvirt_connect_list_networks (value connv, value iv)
     Store_field (rv, i, strv);
     free (names[i]);
   }
+  free (names);
 
   CAMLreturn (rv);
 }
@@ -325,7 +340,7 @@ ocaml_libvirt_connect_list_defined_networks (value connv, value iv)
   CAMLlocal2 (rv, strv);
   virConnectPtr conn = Connect_val (connv);
   int i = Int_val (iv);
-  char *names[i];
+  char **names;
   int r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
@@ -338,8 +353,12 @@ ocaml_libvirt_connect_list_defined_networks (value connv, value iv)
     CAMLreturn (rv);
   }
 
+  names = malloc (sizeof (*names) * i);
+  if (names == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = virConnectListDefinedNetworks (conn, names, i));
-  CHECK_ERROR (r == -1, "virConnectListDefinedNetworks");
+  CHECK_ERROR_CLEANUP (r == -1, free (names), "virConnectListDefinedNetworks");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i) {
@@ -347,6 +366,7 @@ ocaml_libvirt_connect_list_defined_networks (value connv, value iv)
     Store_field (rv, i, strv);
     free (names[i]);
   }
+  free (names);
 
   CAMLreturn (rv);
 }
@@ -381,7 +401,7 @@ ocaml_libvirt_connect_list_storage_pools (value connv, value iv)
   CAMLlocal2 (rv, strv);
   virConnectPtr conn = Connect_val (connv);
   int i = Int_val (iv);
-  char *names[i];
+  char **names;
   int r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
@@ -394,8 +414,12 @@ ocaml_libvirt_connect_list_storage_pools (value connv, value iv)
     CAMLreturn (rv);
   }
 
+  names = malloc (sizeof (*names) * i);
+  if (names == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = virConnectListStoragePools (conn, names, i));
-  CHECK_ERROR (r == -1, "virConnectListStoragePools");
+  CHECK_ERROR_CLEANUP (r == -1, free (names), "virConnectListStoragePools");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i) {
@@ -403,6 +427,7 @@ ocaml_libvirt_connect_list_storage_pools (value connv, value iv)
     Store_field (rv, i, strv);
     free (names[i]);
   }
+  free (names);
 
   CAMLreturn (rv);
 }
@@ -437,7 +462,7 @@ ocaml_libvirt_connect_list_defined_storage_pools (value connv, value iv)
   CAMLlocal2 (rv, strv);
   virConnectPtr conn = Connect_val (connv);
   int i = Int_val (iv);
-  char *names[i];
+  char **names;
   int r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
@@ -450,8 +475,12 @@ ocaml_libvirt_connect_list_defined_storage_pools (value connv, value iv)
     CAMLreturn (rv);
   }
 
+  names = malloc (sizeof (*names) * i);
+  if (names == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = virConnectListDefinedStoragePools (conn, names, i));
-  CHECK_ERROR (r == -1, "virConnectListDefinedStoragePools");
+  CHECK_ERROR_CLEANUP (r == -1, free (names), "virConnectListDefinedStoragePools");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i) {
@@ -459,6 +488,7 @@ ocaml_libvirt_connect_list_defined_storage_pools (value connv, value iv)
     Store_field (rv, i, strv);
     free (names[i]);
   }
+  free (names);
 
   CAMLreturn (rv);
 }
@@ -1795,7 +1825,7 @@ ocaml_libvirt_storage_pool_list_volumes (value poolv, value iv)
   CAMLlocal2 (rv, strv);
   virStoragePoolPtr pool = Pool_val (poolv);
   int i = Int_val (iv);
-  char *names[i];
+  char **names;
   int r;
 
   /* Some libvirt List* functions still throw exceptions if i == 0,
@@ -1808,8 +1838,12 @@ ocaml_libvirt_storage_pool_list_volumes (value poolv, value iv)
     CAMLreturn (rv);
   }
 
+  names = malloc (sizeof (*names) * i);
+  if (names == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = virStoragePoolListVolumes (pool, names, i));
-  CHECK_ERROR (r == -1, "virStoragePoolListVolumes");
+  CHECK_ERROR_CLEANUP (r == -1, free (names), "virStoragePoolListVolumes");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i) {
@@ -1817,6 +1851,7 @@ ocaml_libvirt_storage_pool_list_volumes (value poolv, value iv)
     Store_field (rv, i, strv);
     free (names[i]);
   }
+  free (names);
 
   CAMLreturn (rv);
 }
index 72543d7..69d1b40 100644 (file)
@@ -284,16 +284,21 @@ ocaml_libvirt_connect_node_get_cells_free_memory (value connv,
   int start = Int_val (startv);
   int max = Int_val (maxv);
   int r, i;
-  unsigned long long freemems[max];
+  unsigned long long *freemems;
+
+  freemems = malloc(sizeof (*freemems) * max);
+  if (freemems == NULL)
+    caml_raise_out_of_memory ();
 
   NONBLOCKING (r = virNodeGetCellsFreeMemory (conn, freemems, start, max));
-  CHECK_ERROR (r == -1, "virNodeGetCellsFreeMemory");
+  CHECK_ERROR_CLEANUP (r == -1, free (freemems), "virNodeGetCellsFreeMemory");
 
   rv = caml_alloc (r, 0);
   for (i = 0; i < r; ++i) {
     iv = caml_copy_int64 ((int64_t) freemems[i]);
     Store_field (rv, i, iv);
   }
+  free (freemems);
 
   CAMLreturn (rv);
 }
@@ -421,11 +426,15 @@ ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv)
   CAMLlocal4 (rv, v, v2, v3);
   virDomainPtr dom = Domain_val (domv);
   int nparams = Int_val (nparamsv);
-  virSchedParameter params[nparams];
+  virSchedParameterPtr params;
   int r, i;
 
+  params = malloc (sizeof (*params) * nparams);
+  if (params == NULL)
+    caml_raise_out_of_memory ();
+
   NONBLOCKING (r = virDomainGetSchedulerParameters (dom, params, &nparams));
-  CHECK_ERROR (r == -1, "virDomainGetSchedulerParameters");
+  CHECK_ERROR_CLEANUP (r == -1, free (params), "virDomainGetSchedulerParameters");
 
   rv = caml_alloc (nparams, 0);
   for (i = 0; i < nparams; ++i) {
@@ -461,6 +470,7 @@ ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv)
     }
     Store_field (v, 1, v2);
   }
+  free (params);
   CAMLreturn (rv);
 }
 
@@ -471,10 +481,14 @@ ocaml_libvirt_domain_set_scheduler_parameters (value domv, value paramsv)
   CAMLlocal1 (v);
   virDomainPtr dom = Domain_val (domv);
   int nparams = Wosize_val (paramsv);
-  virSchedParameter params[nparams];
+  virSchedParameterPtr params;
   int r, i;
   char *name;
 
+  params = malloc (sizeof (*params) * nparams);
+  if (params == NULL)
+    caml_raise_out_of_memory ();
+
   for (i = 0; i < nparams; ++i) {
     v = Field (paramsv, i);    /* Points to the two-element tuple. */
     name = String_val (Field (v, 0));
@@ -512,6 +526,7 @@ ocaml_libvirt_domain_set_scheduler_parameters (value domv, value paramsv)
   }
 
   NONBLOCKING (r = virDomainSetSchedulerParameters (dom, params, nparams));
+  free (params);
   CHECK_ERROR (r == -1, "virDomainSetSchedulerParameters");
 
   CAMLreturn (Val_unit);
@@ -554,15 +569,21 @@ ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv)
   virDomainPtr dom = Domain_val (domv);
   int maxinfo = Int_val (maxinfov);
   int maplen = Int_val (maplenv);
-  virVcpuInfo info[maxinfo];
-  unsigned char cpumaps[maxinfo * maplen];
+  virVcpuInfoPtr info;
+  unsigned char *cpumaps;
   int r, i;
 
-  memset (info, 0, sizeof (virVcpuInfo) * maxinfo);
-  memset (cpumaps, 0, maxinfo * maplen);
+  info = calloc (maxinfo, sizeof (*info));
+  if (info == NULL)
+    caml_raise_out_of_memory ();
+  cpumaps = calloc (maxinfo * maplen, sizeof (*cpumaps));
+  if (cpumaps == NULL) {
+    free (info);
+    caml_raise_out_of_memory ();
+  }
 
   NONBLOCKING (r = virDomainGetVcpus (dom, info, maxinfo, cpumaps, maplen));
-  CHECK_ERROR (r == -1, "virDomainPinVcpu");
+  CHECK_ERROR_CLEANUP (r == -1, free (info); free (cpumaps), "virDomainPinVcpu");
 
   /* Copy the virVcpuInfo structures. */
   infov = caml_alloc (maxinfo, 0);
@@ -584,6 +605,9 @@ ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv)
   Store_field (rv, 1, infov);
   Store_field (rv, 2, strv);
 
+  free (info);
+  free (cpumaps);
+
   CAMLreturn (rv);
 }