summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryallop <yallop@gmail.com>2016-09-26 14:06:57 +0100
committerDamien Doligez <damien.doligez@gmail.com>2016-09-26 15:06:57 +0200
commit89aff47a005f9a17417e7c76ee4e679e74bed5d5 (patch)
tree9ab69a3c09fdc031d8e69c5554df309ceca033f1
parentf872d67d4e97a6072f5891b5aef3c5f7e39e4a25 (diff)
downloadocaml-89aff47a005f9a17417e7c76ee4e679e74bed5d5.tar.gz
Detect integer overflow in Array.concat (#810)
* Check for overflow in caml_array_gather. * Add a changelog entry for the check for overflow in Array.concat.
-rw-r--r--Changes5
-rw-r--r--byterun/array.c5
2 files changed, 8 insertions, 2 deletions
diff --git a/Changes b/Changes
index 3700690d5a..9058a6bf0e 100644
--- a/Changes
+++ b/Changes
@@ -56,7 +56,10 @@ Next version (tbd):
(Xavier Leroy)
- GPR#814: fix the Buffer.add_substring bounds check to handle overflow
- (Jeremy Yallop)
+ (Jeremy Yallop)
+
+- GPR#810: check for integer overflow in Array.concat
+ (Jeremy Yallop)
OCaml 4.04.0:
diff --git a/byterun/array.c b/byterun/array.c
index dd694affc2..11f2b51ad5 100644
--- a/byterun/array.c
+++ b/byterun/array.c
@@ -26,6 +26,8 @@
/* Why is caml/spacetime.h included conditionnally sometimes and not here ? */
#include "caml/spacetime.h"
+static const mlsize_t mlsize_t_max = -1;
+
/* returns number of elements (either fields or floats) */
CAMLexport mlsize_t caml_array_length(value array)
{
@@ -314,6 +316,7 @@ static value caml_array_gather(intnat num_arrays,
size = 0;
isfloat = 0;
for (i = 0; i < num_arrays; i++) {
+ if (mlsize_t_max - lengths[i] < size) caml_invalid_argument("Array.concat");
size += lengths[i];
if (Tag_val(arrays[i]) == Double_array_tag) isfloat = 1;
}
@@ -323,8 +326,8 @@ static value caml_array_gather(intnat num_arrays,
}
else if (isfloat) {
/* This is an array of floats. We can use memcpy directly. */
+ if (size > Max_wosize/Double_wosize) caml_invalid_argument("Array.concat");
wsize = size * Double_wosize;
- if (wsize > Max_wosize) caml_invalid_argument("Array.concat");
res = caml_alloc(wsize, Double_array_tag);
for (i = 0, pos = 0; i < num_arrays; i++) {
memcpy((double *)res + pos,