CVE-2015-8869: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: OCaml before 4.03.0 does not properly handle sign extensions, which allows remote attackers to conduct buffer overflow attacks or obtain sensitive information as demonstrated by a long string to the String.copy function.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
CVSS v3 base score: 9.1
Published: 2016-06-13T19:59Z
Repository: https://github.com/ocaml/ocaml
Language: C
Files changed: Changes, VERSION, byterun/alloc.c, byterun/intern.c, byterun/str.c
Commit date: 2015-10-19 15:47:33 +0000
Commit message: fix PR#7003 and a few other bugs caused by misuse of Int_val

git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@16525 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02

Diff: diff --git a/Changes b/Changes
index 047b437dd..668f85190 100644
--- a/Changes
+++ b/Changes
@@ -202,12 +202,14 @@ Bug fixes:
 - PR#6982: unexpected type error when packing a module alias
 - PR#6985: `module type of struct include Bar end exposes
            %s#row when Bar contains private row types
 - PR#6992: Segfault from bug in GADT/module typing
 - PR#6993: Segfault from recursive modules violating exhaustiveness assumptions
+- PR#7003: String.sub causes segmentation fault
+  (Damien Doligez, report by Radek Micek)
 - PR#7008: Fatal error in ocamlc with empty compilation unit name
-  (Damien Doligez)
+  (Damien Doligez, report by Cesar Kunz)
 - PR#7012: Variable name forgotten when it starts with a capital letter
   (Jacques Garrigue, Gabriel Scherer, report by Thomas Leonard and Octachron)
 - PR#7016: Stack overflow in GADT typing
 - GPR#205: Clear caml_backtrace_last_exn before registering as root (report
   and fix by Frederic Bour)
diff --git a/VERSION b/VERSION
index 5310f512b..fb6ef7133 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-4.03.0+dev10-2015-07-29
+4.03.0+dev11-2015-10-19
 
 # The version string is the first line of this file.
 # It must be in the format described in stdlib/sys.mli
diff --git a/byterun/alloc.c b/byterun/alloc.c
index 96a21bf1f..0db994724 100644
--- a/byterun/alloc.c
+++ b/byterun/alloc.c
@@ -151,11 +151,11 @@ CAMLexport int caml_convert_flag_list(value list, int *flags)
 /* For compiling let rec over values */
 
 /* [size] is a [value] representing number of words (fields) */
 CAMLprim value caml_alloc_dummy(value size)
 {
-  mlsize_t wosize = Int_val(size);
+  mlsize_t wosize = Long_val(size);
 
   if (wosize == 0) return Atom(0);
   return caml_alloc (wosize, 0);
 }
 
@@ -167,11 +167,11 @@ CAMLprim value caml_alloc_dummy_function(value size,value arity)
 }
 
 /* [size] is a [value] representing number of floats. */
 CAMLprim value caml_alloc_dummy_float (value size)
 {
-  mlsize_t wosize = Int_val(size) * Double_wosize;
+  mlsize_t wosize = Long_val(size) * Double_wosize;
 
   if (wosize == 0) return Atom(0);
   return caml_alloc (wosize, 0);
 }
 
diff --git a/byterun/intern.c b/byterun/intern.c
index 89d13d116..7b8d0497b 100644
--- a/byterun/intern.c
+++ b/byterun/intern.c
@@ -289,11 +289,11 @@ static void intern_rec(value *dest)
   dest = sp->dest;
   switch (sp->op) {
   case OFreshOID:
     /* Refresh the object ID */
     /* but do not do it for predefined exception slots */
-    if (Int_val(Field((value)dest, 1)) >= 0)
+    if (Long_val(Field((value)dest, 1)) >= 0)
       caml_set_oo_id((value)dest);
     /* Pop item and iterate */
     sp--;
     break;
   case OShift:
diff --git a/byterun/str.c b/byterun/str.c
index 5ad4e2941..885772f74 100644
--- a/byterun/str.c
+++ b/byterun/str.c
@@ -264,11 +264,11 @@ CAMLprim value caml_string_greaterequal(value s1, value s2)
 }
 
 CAMLprim value caml_blit_string(value s1, value ofs1, value s2, value ofs2,
                                 value n)
 {
-  memmove(&Byte(s2, Long_val(ofs2)), &Byte(s1, Long_val(ofs1)), Int_val(n));
+  memmove(&Byte(s2, Long_val(ofs2)), &Byte(s1, Long_val(ofs1)), Long_val(n));
   return Val_unit;
 }
 
 CAMLprim value caml_fill_string(value s, value offset, value len, value init)
 {
@@ -276,11 +276,11 @@ CAMLprim value caml_fill_string(value s, value offset, value len, value init)
   return Val_unit;
 }
 
 CAMLprim value caml_bitvect_test(value bv, value n)
 {
-  int pos = Int_val(n);
+  intnat pos = Long_val(n);
   return Val_int(Byte_u(bv, pos >> 3) & (1 << (pos & 7)));
 }
 
 CAMLexport value caml_alloc_sprintf(const char * format, ...)
 {

Vulnerable code:   (Damien Doligez)
4.03.0+dev10-2015-07-29
  mlsize_t wosize = Int_val(size);
  mlsize_t wosize = Int_val(size) * Double_wosize;
    if (Int_val(Field((value)dest, 1)) >= 0)
  memmove(&Byte(s2, Long_val(ofs2)), &Byte(s1, Long_val(ofs1)), Int_val(n));
  int pos = Int_val(n);
Fixed code: - PR#7003: String.sub causes segmentation fault
  (Damien Doligez, report by Radek Micek)
  (Damien Doligez, report by Cesar Kunz)
4.03.0+dev11-2015-10-19
  mlsize_t wosize = Long_val(size);
  mlsize_t wosize = Long_val(size) * Double_wosize;
    if (Long_val(Field((value)dest, 1)) >= 0)
  memmove(&Byte(s2, Long_val(ofs2)), &Byte(s1, Long_val(ofs1)), Long_val(n));
  intnat pos = Long_val(n);