https://bugs.gentoo.org/755257 Needed for both fixing the CVE + compatibility with Debian for e.g. Unison. From c6ca3afc78b75d7748e4e09e56c6b020418be06e Mon Sep 17 00:00:00 2001 From: Stephane Glondu Date: Fri, 25 Jan 2019 14:34:23 +0100 Subject: [PATCH] Fix integer overflows when unmarshaling a bigarray Malicious or corrupted marshaled data can result in a bigarray with impossibly large dimensions that cause overflow when computing the in-memory size of the bigarray. Disaster ensues when the data is read in a too small memory area. This commit checks for overflows when computing the in-memory size of the bigarray. This patch is based on one by Xavier Leroy and has been modified to use caml_ba_multov instead of caml_umul_overflow which is unavailable in OCaml 4.05.0. The original commit hash is 85162eee9d4072fa9c2f498f03cd94e357033eec. Origin: https://github.com/ocaml/ocaml/pull/1718 Bug: https://github.com/ocaml/ocaml/issues/7765 Bug-Debian: https://bugs.debian.org/895472 Bug-CVE: CVE-2018-9838 --- a/otherlibs/bigarray/bigarray_stubs.c +++ b/otherlibs/bigarray/bigarray_stubs.c @@ -966,22 +966,34 @@ static void caml_ba_deserialize_longarray(void * dest, intnat num_elts) uintnat caml_ba_deserialize(void * dst) { struct caml_ba_array * b = dst; - int i, elt_size; - uintnat num_elts; + int i; + uintnat num_elts, size; + int overflow; /* Read back header information */ b->num_dims = caml_deserialize_uint_4(); + if (b->num_dims < 0 || b->num_dims > CAML_BA_MAX_NUM_DIMS) + caml_deserialize_error("input_value: wrong number of bigarray dimensions"); b->flags = caml_deserialize_uint_4() | CAML_BA_MANAGED; b->proxy = NULL; for (i = 0; i < b->num_dims; i++) b->dim[i] = caml_deserialize_uint_4(); - /* Compute total number of elements */ - num_elts = caml_ba_num_elts(b); - /* Determine element size in bytes */ + /* Compute total number of elements. Watch out for overflows (MPR#7765). */ + num_elts = 1; + for (i = 0; i < b->num_dims; i++) { + overflow = 0; + num_elts = caml_ba_multov(num_elts, b->dim[i], &overflow); + if (overflow) + caml_deserialize_error("input_value: size overflow for bigarray"); + } + /* Determine array size in bytes. Watch out for overflows (MPR#7765). */ if ((b->flags & CAML_BA_KIND_MASK) > CAML_BA_CHAR) caml_deserialize_error("input_value: bad bigarray kind"); - elt_size = caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; + overflow = 0; + size = caml_ba_multov(num_elts, caml_ba_element_size[b->flags & CAML_BA_KIND_MASK], &overflow); + if (overflow) + caml_deserialize_error("input_value: size overflow for bigarray"); /* Allocate room for data */ - b->data = malloc(elt_size * num_elts); + b->data = malloc(size); if (b->data == NULL) caml_deserialize_error("input_value: out of memory for bigarray"); /* Read data */