Bigarray.reshape does not seem to handle overflow well, allowing to read into uninitialized memory.
Below example shows how data pointer isn't reallocated, caml_ba_num_elts still returns 0, but .get() into uninitialized memory is allowed:
Array1.create 0
arr->data: 0xebb0480
elements: 0
arr.get(5) exception: Invalid_argument("index out of bounds")
Bigarray.reshape [|8; 2305843009213693952|]
Size in bytes: 0 (dim1: 8, dim2: 2305843009213693952)
arr->data: 0xebb0480
elements: 0
arr[5][5]: -2134031706542294431 <--- this value is random on every program invocation
It seems like caml_umul_overflow in caml_ba_alloc should catch this, raising Out_of_memory, but this doesn't seem to be the case.
Source code of the example above.
bin/dune:
(executable
(foreign_stubs
(language c)
(names reshape_stubs)
)
(public_name reshape)
(name main)
(libraries reshape))
bin/main.ml:
external elements : ('a, 'b, 'c) Bigarray.Genarray.t -> int = "stub_arr_size"
let _ =
let open Bigarray in
print_endline "Array1.create 0" ;
let arr = Array1.create int c_layout 0 in
Printf.printf "elements: %d\n" (elements (genarray_of_array1 arr)) ;
let _ =
try Array1.get arr 5
with e ->
Printf.printf "arr.get(5) exception: %s\n" (Printexc.to_string e) ;
1
in
print_endline "\nBigarray.reshape [|8; 2305843009213693952|]" ;
let x =
array2_of_genarray
(reshape (genarray_of_array1 arr) [|8; 2305843009213693952|])
in
print_endline
(Printf.sprintf "Size in bytes: %d (dim1: %d, dim2: %d)\n"
(Array2.size_in_bytes x) (Array2.dim1 x) (Array2.dim2 x)
) ;
Printf.printf "elements: %d\n" (elements (genarray_of_array2 x)) ;
Printf.printf "arr[5][5]: %d\n" (Array2.get x 5 5)
bin/reshape_stubs.c:
#include <caml/bigarray.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
CAMLprim value
stub_arr_size (value arr)
{
CAMLparam1(arr);
printf("arr->data: %p\n", Caml_ba_array_val(arr)->data);
CAMLreturn(Val_int(caml_ba_num_elts(Caml_ba_array_val(arr))));
}
Bigarray.reshapedoes not seem to handle overflow well, allowing to read into uninitialized memory.Below example shows how
datapointer isn't reallocated,caml_ba_num_eltsstill returns 0, but.get()into uninitialized memory is allowed:It seems like
caml_umul_overflowincaml_ba_allocshould catch this, raisingOut_of_memory, but this doesn't seem to be the case.Source code of the example above.
bin/dune:bin/main.ml:bin/reshape_stubs.c: