Skip to content

Commit 22f7925

Browse files
authored
Fix: static eval of String.get (#770)
1 parent 2bc7622 commit 22f7925

File tree

5 files changed

+67
-16
lines changed

5 files changed

+67
-16
lines changed

compiler/lib/eval.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,9 @@ let eval_prim x =
131131
| "caml_tan_float", _ -> float_unop l tan
132132
| ("caml_string_get" | "caml_string_unsafe_get"), [(String s | IString s); Int pos]
133133
->
134-
if Config.Flag.safe_string () && String.length s > Int.to_int pos
135-
then Some (Int (Int.of_int (Char.code s.[Int.to_int pos])))
134+
let pos = Int.to_int pos in
135+
if Config.Flag.safe_string () && pos >= 0 && pos < String.length s
136+
then Some (Int (Int.of_int (Char.code s.[pos])))
136137
else None
137138
| "caml_string_equal", [String s1; String s2] -> bool (s1 = s2)
138139
| "caml_string_notequal", [String s1; String s2] -> bool (s1 <> s2)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
(* Js_of_ocaml tests
2+
* http://www.ocsigen.org/js_of_ocaml/
3+
* Copyright (C) 2019 Hugo Heuzard
4+
*
5+
* This program is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation; either version 2 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program; if not, write to the Free Software
17+
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18+
*)
19+
20+
open Util
21+
22+
let%expect_test "static eval of string get" =
23+
let cmo =
24+
compile_ocaml_to_bytecode
25+
{|
26+
let lr = ref []
27+
let black_box v = lr := (Obj.repr v) :: !lr
28+
29+
let constant = "abcdefghijklmnopqrstuvwxyz"
30+
31+
let call_with_char c = black_box c
32+
33+
let ex = call_with_char constant.[-10] ;;
34+
black_box ex
35+
let ax = call_with_char constant.[6] ;;
36+
black_box ax
37+
let bx = call_with_char constant.[30] ;;
38+
black_box bx ;;
39+
|}
40+
in
41+
let program = parse_js (print_compiled_js ~pretty:true cmo) in
42+
print_var_decl program "ex";
43+
print_var_decl program "ax";
44+
print_var_decl program "bx";
45+
[%expect
46+
{|
47+
var ex = call_with_char(caml_string_get(constant,- 10));
48+
var ax = call_with_char(103);
49+
var bx = call_with_char(caml_string_get(constant,30)); |}]

compiler/tests/expect_tests/util.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,16 @@ let expression_to_string ?(compact = false) e =
124124
Pretty_print.set_compact pp compact;
125125
Js_output.program pp e;
126126
Buffer.contents buffer
127+
128+
let print_var_decl program n =
129+
let {var_decls; _} =
130+
find_javascript
131+
~var_decl:(function
132+
| Javascript.S {name; _}, _ when name = n -> true
133+
| _ -> false)
134+
program
135+
in
136+
print_string (Format.sprintf "var %s = " n);
137+
match var_decls with
138+
| [(_, Some (expression, _))] -> print_string (expression_to_string expression)
139+
| _ -> print_endline "not found"

compiler/tests/expect_tests/util.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,5 @@ val find_javascript :
3838
-> find_result
3939

4040
val expression_to_string : ?compact:bool -> Javascript.expression -> string
41+
42+
val print_var_decl : Javascript.program -> string -> unit

compiler/tests/expect_tests/variable_declaration_output.ml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,6 @@
1818
*)
1919

2020
open Util
21-
module J = Js_of_ocaml_compiler.Javascript
22-
23-
let print_var_decl program n =
24-
let {var_decls; _} =
25-
find_javascript
26-
~var_decl:(function
27-
| J.S {name; _}, _ when name = n -> true
28-
| _ -> false)
29-
program
30-
in
31-
print_string (Format.sprintf "var %s = " n);
32-
match var_decls with
33-
| [(_, Some (expression, _))] -> print_string (expression_to_string expression)
34-
| _ -> print_endline "not found"
3521

3622
let%expect_test _ =
3723
let cmo =

0 commit comments

Comments
 (0)