Package: ocaml / 4.05.0-11

0012-Integer-overflows-when-unmarshaling-a-bigarray.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
From: Stephane Glondu <steph@glondu.net>
Date: Fri, 25 Jan 2019 14:34:23 +0100
Subject: 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 has been modified from upstream one to use caml_ba_multov
instead of caml_umul_overflow which is unavailable in OCaml 4.05.0.

Origin: https://github.com/ocaml/ocaml/pull/1718
Bug: https://caml.inria.fr/mantis/view.php?id=7765
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=895472
Bug-CVE: CVE-2018-9838
---
 otherlibs/bigarray/bigarray_stubs.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/otherlibs/bigarray/bigarray_stubs.c b/otherlibs/bigarray/bigarray_stubs.c
index cb38bef..995739d 100644
--- 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 */