9e17f24 bound checking bug with caml_string_{get,set}{16,32,64}: fix the runtime C code

Authored and Committed by Gabriel Scherer 10 years ago
    bound checking bug with caml_string_{get,set}{16,32,64}: fix the runtime C code
    
    As notified by Nicolas Trangez, the following program behaves in an
    unexpected way by returning 0 instead of failing with an out-of-bound
    exception:
    
      external get16 : string -> int -> int = "%caml_string_get16"
      let test = get16 "" 0
    
    caml_string_get16(str, idx) will access indices (idx) and (idx+1). The
    bound-checking code is currently implemented as:
    
       if (idx < 0 || idx >= caml_string_length(str) - 1) caml_array_bound_error();
    
    This is wrong as caml_string_length returns an mlsize_t which is
    unsigned, so substracting 1 gets buggy when the size is 0. The test
    should be written as follow:
    
       if (idx < 0 || idx + 1 >= caml_string_length(str)) caml_array_bound_error();
    
    Note 1: we can exploit this bug to make out-of-bound access to
    a string, but I think get16 examples will run into the padding
    characters of OCaml strings and behave in a not-too-wrong way. It may
    also be the case of get32, but get64 will access 7 bytes, so access
    memory outside the string:
    
      # external set64: string -> int -> int -> unit = "%caml_string_get64";;
      external set64 : string -> int -> int -> unit = "%caml_string_get64"
      # set64 "" 0 0;;
      Segmentation fault
    
    Note 2: this first commit only fixes the C code in byterun/str.c. Only
    ocamlc actually uses these functions when the compiler primitive is
    used ("%caml_string_get16" instead of "caml_string_get16"). ocamlopt
    generates ocaml code directly, and this part has yet to be fixed in
    a following commit.
    
    git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@14267 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
    
        
file modified
+6 -6