TC-B Samples

Here is an example with an out-of-bounds array subscript, run with HAVM.

subscript-read.tig
let
  type int_array = array of int
  var foo : int_array := int_array [10] of 3
in
  /* Out-of-bounds access.  */
  foo[20]
end
tc --bounds-checks-add -A subscript-read.tig
$ tc --bounds-checks-add -A subscript-read.tig
/* == Abstract Syntax Tree. == */

primitive print(string_0 : string)
primitive print_err(string_1 : string)
primitive print_int(int_2 : int)
primitive flush()
primitive getchar() : string
primitive ord(string_3 : string) : int
primitive chr(code_4 : int) : string
primitive size(string_5 : string) : int
primitive streq(s1_6 : string, s2_7 : string) : int
primitive strcmp(s1_8 : string, s2_9 : string) : int
primitive substring(string_10 : string, start_11 : int, length_12 : int) : string
primitive concat(fst_13 : string, snd_14 : string) : string
primitive not(boolean_15 : int) : int
primitive exit(status_16 : int)
function _main() =
  let
    type __int_array = array of int
    type _int_array = {
      arr : __int_array,
      size : int
    }
    function _check_bounds(a : _int_array, index : int, location : string) : int =
      (
        if if index < 0
              then 1
              else (index >= a.size) <> 0
          then (
              print_err(location);
              print_err(": array index out of bounds.\n");
              exit(120)
            )
          else ();
        index
      )
  in
    (
      let
        type _box_int_array_17 = {
          arr : int_array_17,
          size : int
        }
        type int_array_17 = array of int
        var foo_18 : _box_int_array_17 := let
            var _size := 10
          in
            _box_int_array_17 {
              arr = int_array_17 [_size] of 3,
              size = _size
            }
          end
      in
        foo_18.arr[_check_bounds(_cast(foo_18, _int_array), 20, "subscript-read.tig:6.3-9")]
      end;
      ()
    )
  end
$ echo $?
0
tc --bounds-checks-add -L subscript-read.tig > subscript-read.lir
$ tc --bounds-checks-add -L subscript-read.tig > subscript-read.lir

$ echo $?
0
havm -l subscript-read.lir
$ havm -l subscript-read.lir
subscript-read.tig:6.3-9: array index out of bounds.
$ echo $?
120

And here is an example with an out-of-bounds assignment to an array cell, tested with Nolimips.

subscript-write.tig
let
  type int_array = array of int
  var foo := int_array [10] of 3
in
  /* Out-of-bounds assignment.  */
  foo[42] := 51
end
tc --bounds-checks-add -A subscript-write.tig
$ tc --bounds-checks-add -A subscript-write.tig
/* == Abstract Syntax Tree. == */

primitive print(string_0 : string)
primitive print_err(string_1 : string)
primitive print_int(int_2 : int)
primitive flush()
primitive getchar() : string
primitive ord(string_3 : string) : int
primitive chr(code_4 : int) : string
primitive size(string_5 : string) : int
primitive streq(s1_6 : string, s2_7 : string) : int
primitive strcmp(s1_8 : string, s2_9 : string) : int
primitive substring(string_10 : string, start_11 : int, length_12 : int) : string
primitive concat(fst_13 : string, snd_14 : string) : string
primitive not(boolean_15 : int) : int
primitive exit(status_16 : int)
function _main() =
  let
    type __int_array = array of int
    type _int_array = {
      arr : __int_array,
      size : int
    }
    function _check_bounds(a : _int_array, index : int, location : string) : int =
      (
        if if index < 0
              then 1
              else (index >= a.size) <> 0
          then (
              print_err(location);
              print_err(": array index out of bounds.\n");
              exit(120)
            )
          else ();
        index
      )
  in
    (
      let
        type _box_int_array_17 = {
          arr : int_array_17,
          size : int
        }
        type int_array_17 = array of int
        var foo_18 := let
            var _size := 10
          in
            _box_int_array_17 {
              arr = int_array_17 [_size] of 3,
              size = _size
            }
          end
      in
        foo_18.arr[_check_bounds(_cast(foo_18, _int_array), 42, "subscript-write.tig:6.3-9")] := 51
      end;
      ()
    )
  end
$ echo $?
0
tc --bounds-checks-add -S subscript-write.tig > subscript-write.s
$ tc --bounds-checks-add -S subscript-write.tig > subscript-write.s

$ echo $?
0
nolimips -l nolimips -Nue subscript-write.s
$ nolimips -l nolimips -Nue subscript-write.s
subscript-write.tig:6.3-9: array index out of bounds.
$ echo $?
120