From: Pino Toscano Date: Thu, 30 Aug 2018 10:13:41 +0000 (+0200) Subject: Avoid VLAs with size depending on user input X-Git-Url: http://git.annexia.org/?p=ocaml-libvirt.git;a=commitdiff_plain;h=c27cacae2abac36e2ae89e3e354ec7b0ba8a70dc Avoid VLAs with size depending on user input 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. --- diff --git a/libvirt/generator.pl b/libvirt/generator.pl index 34801ba..ea1b2be 100755 --- a/libvirt/generator.pl +++ b/libvirt/generator.pl @@ -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); " diff --git a/libvirt/libvirt_c.c b/libvirt/libvirt_c.c index 8d51944..0e731a8 100644 --- a/libvirt/libvirt_c.c +++ b/libvirt/libvirt_c.c @@ -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); } diff --git a/libvirt/libvirt_c_oneoffs.c b/libvirt/libvirt_c_oneoffs.c index 72543d7..69d1b40 100644 --- a/libvirt/libvirt_c_oneoffs.c +++ b/libvirt/libvirt_c_oneoffs.c @@ -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); }