From a774f5e73389d8b1157444385573e6c647d9fff9 Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Mon, 7 Dec 2015 10:12:21 -0800 Subject: [PATCH] compile with -safe-string Summary: public so that we don't introduce more string mutations in the future. Reviewed By: jberdine Differential Revision: D2729167 fb-gh-sync-id: 746319a --- configure.ac | 10 ++++------ infer/src/Makefile.in | 10 +++++++--- infer/src/backend/DB.ml | 4 ++-- infer/src/backend/DB.mli | 4 ++-- infer/src/backend/dotty.ml | 9 +++++---- infer/src/checkers/codeQuery.ml | 3 ++- infer/src/checkers/models.ml | 14 +++++++------- m4/ac_ocaml_check_native_bytes.m4 | 22 ++++++++++++++++++++++ m4/ac_ocaml_check_safe_string.m4 | 20 ++++++++++++++++++++ 9 files changed, 71 insertions(+), 25 deletions(-) create mode 100644 m4/ac_ocaml_check_native_bytes.m4 create mode 100644 m4/ac_ocaml_check_safe_string.m4 diff --git a/configure.ac b/configure.ac index 3eb02a88e..082548733 100644 --- a/configure.ac +++ b/configure.ac @@ -54,13 +54,11 @@ AC_ASSERT_OCAML_PKG([easy-format]) AC_ASSERT_OCAML_PKG([ptrees]) AC_ASSERT_OCAML_PKG([yojson]) -OCAMLVERSION_MAJOR=$(printf $OCAMLVERSION | cut -d . -f 1) -OCAMLVERSION_MINOR=$(printf $OCAMLVERSION | cut -d . -f 2) +AC_OCAML_CHECK_NATIVE_BYTES +AC_OCAMLC_CHECK_SAFE_STRING -OCAML_PKG_bytes=no -# need the bytes package for OCaml version < 4.02.0 -if test "$OCAMLVERSION_MAJOR" -le 4 && test "$OCAMLVERSION_MINOR" -lt 2; then -AC_ASSERT_OCAML_PKG([bytes]) +if test "$OCAML_HAS_NATIVE_BYTES" = "no"; then + AC_ASSERT_OCAML_PKG([bytes]) fi AC_CHECK_TOOL([ATDGEN], [atdgen], [no]) diff --git a/infer/src/Makefile.in b/infer/src/Makefile.in index 206729917..b5c3819fb 100644 --- a/infer/src/Makefile.in +++ b/infer/src/Makefile.in @@ -44,9 +44,9 @@ OCAML_LIBS = unix str atdgen OCAML_MODS = easy_format bi_util bi_share bi_outbuf bi_inbuf bi_vint bi_io yojson ag_oj_run ag_ob_run ag_util # backwards compatibility with OCaml version < 4.02.0 -ifneq (@OCAML_PKG_bytes@,no) -BYTES_INCLUDE_DIR = @OCAML_PKG_PATH_bytes@ -OCAML_INCLUDES := $(OCAML_INCLUDES),-I,$(BYTES_INCLUDE_DIR) +ifeq (@OCAML_HAS_NATIVE_BYTES@,no) +OCAML_INCLUDES := $(OCAML_INCLUDES),-I,@OCAML_PKG_PATH_bytes@ +OCAML_LIBS += bytes endif OCAMLBUILD_OPTIONS = -lflags -annot \ @@ -56,6 +56,10 @@ OCAMLBUILD_OPTIONS = -lflags -annot \ $(addprefix -lib ,$(OCAML_LIBS)) \ $(addprefix -mod ,$(OCAML_MODS)) +ifeq (@OCAMLC_HAS_SAFE_STRING@,yes) +OCAMLBUILD_OPTIONS += -cflags -safe-string +endif + #### Backend declarations #### BACKEND_SOURCES = backend diff --git a/infer/src/backend/DB.ml b/infer/src/backend/DB.ml index 7d77cc42b..a5439946b 100644 --- a/infer/src/backend/DB.ml +++ b/infer/src/backend/DB.ml @@ -234,8 +234,8 @@ let update_file_with_lock dir fname update = let buf = read_whole_file fd in reset_file fd; let str = update buf in - let i = Unix.write fd str 0 (String.length str) in - if (i = (String.length str)) + let i = Unix.write fd str 0 (Bytes.length str) in + if (i = (Bytes.length str)) then (Unix.lockf fd Unix.F_ULOCK 0; Unix.close fd) else (L.err "@.save_with_lock: fail on path: %s@." path; assert false) diff --git a/infer/src/backend/DB.mli b/infer/src/backend/DB.mli index 23c0b8581..d0101a793 100644 --- a/infer/src/backend/DB.mli +++ b/infer/src/backend/DB.mli @@ -133,13 +133,13 @@ val find_source_dirs : unit -> source_dir list val create_dir : string -> unit (** Read a file using a lock to allow write attempts in parallel. *) -val read_file_with_lock : string -> string -> string option +val read_file_with_lock : string -> string -> Bytes.t option (** Update the file contents with the update function provided. If the directory does not exist, it is created. If the file does not exist, it is created, and update is given the empty string. A lock is used to allow write attempts in parallel. *) -val update_file_with_lock : string -> string -> (string -> string) -> unit +val update_file_with_lock : string -> string -> (Bytes.t -> Bytes.t) -> unit (** get the path of the global type environment (only used in Java) *) val global_tenv_fname : unit -> filename diff --git a/infer/src/backend/dotty.ml b/infer/src/backend/dotty.ml index e4f9ade22..e308fe04e 100644 --- a/infer/src/backend/dotty.ml +++ b/infer/src/backend/dotty.ml @@ -108,15 +108,16 @@ let exp_is_neq_zero e = (* replace a dollar sign in a name with a D. We need this because dotty get confused if there is*) (* a dollar sign i a label*) let strip_special_chars s = + let b = Bytes.of_string s in let replace st c c' = - if String.contains st c then begin - let idx = String.index st c in + if Bytes.contains st c then begin + let idx = Bytes.index st c in try Bytes.set st idx c'; st with Invalid_argument _ -> L.out "@\n@\n Invalid argument!!! @\n @.@.@."; assert false end else st in - let s0 = replace s '(' 'B' in + let s0 = replace b '(' 'B' in let s1 = replace s0 '$' 'D' in let s2 = replace s1 '#' 'H' in let s3 = replace s2 '&' 'E' in @@ -124,7 +125,7 @@ let strip_special_chars s = let s5 = replace s4 ')' 'B' in let s6 = replace s5 '+' 'P' in let s7 = replace s6 '-' 'M' in - s7 + Bytes.to_string s7 let rec strexp_to_string pe coo f se = match se with diff --git a/infer/src/checkers/codeQuery.ml b/infer/src/checkers/codeQuery.ml index 4a1a1bb7a..01d7839d4 100644 --- a/infer/src/checkers/codeQuery.ml +++ b/infer/src/checkers/codeQuery.ml @@ -28,7 +28,8 @@ let parse_query s = query with | Parsing.Parse_error -> - L.stdout "@.parsing stops on line %d: \n\n%s@." !CodequeryLexer.line_number buf.Lexing.lex_buffer; + let lexbuf = Bytes.to_string buf.Lexing.lex_buffer in + L.stdout "@.parsing stops on line %d: \n\n%s@." !CodequeryLexer.line_number lexbuf; assert false let query_ast = diff --git a/infer/src/checkers/models.ml b/infer/src/checkers/models.ml index b1000ae87..af2c714ba 100644 --- a/infer/src/checkers/models.ml +++ b/infer/src/checkers/models.ml @@ -40,22 +40,22 @@ module Inference = struct let update_count_str s_old = let n = - if s_old = "" then 0 - else try int_of_string s_old with + if s_old = Bytes.empty then 0 + else try int_of_string (Bytes.to_string s_old) with | Failure _ -> - L.stderr "int_of_string %s@." s_old; + L.stderr "int_of_string %s@." (Bytes.to_string s_old); assert false in - string_of_int (n + 1) + Bytes.of_string (string_of_int (n + 1)) let update_boolvec_str _s size index bval = - let s = if _s = "" then String.make size '0' else _s in + let s = if _s = Bytes.empty then Bytes.make size '0' else _s in Bytes.set s index (if bval then '1' else '0'); s let mark_file update_str dir fname = DB.update_file_with_lock dir fname update_str; match DB.read_file_with_lock dir fname with - | Some buf -> L.stderr "Read %s: %s@." fname buf + | Some buf -> L.stderr "Read %s: %s@." fname (Bytes.to_string buf) | None -> L.stderr "Read %s: None@." fname let mark_file_count = mark_file update_count_str @@ -88,7 +88,7 @@ module Inference = struct | None -> None | Some buf -> let boolvec = ref [] in - String.iter (fun c -> boolvec := (c = '1') :: !boolvec) buf; + Bytes.iter (fun c -> boolvec := (c = '1') :: !boolvec) buf; Some (IList.rev !boolvec) end (* Inference *) diff --git a/m4/ac_ocaml_check_native_bytes.m4 b/m4/ac_ocaml_check_native_bytes.m4 new file mode 100644 index 000000000..18b0966a9 --- /dev/null +++ b/m4/ac_ocaml_check_native_bytes.m4 @@ -0,0 +1,22 @@ +dnl Copyright (c) 2015 - present Facebook, Inc. +dnl All rights reserved. +dnl +dnl This source code is licensed under the BSD style license found in the +dnl LICENSE file in the root directory of this source tree. An additional grant +dnl of patent rights can be found in the PATENTS file in the same directory. + +AC_DEFUN([AC_OCAML_CHECK_NATIVE_BYTES], +[dnl + OCAML_HAS_NATIVE_BYTES=no + AC_MSG_CHECKING([if OCaml supports the native 'bytes' type]) + cat > conftest.ml <&5 2>&5 ; then + AC_MSG_RESULT([yes]) + OCAML_HAS_NATIVE_BYTES=yes + else + AC_MSG_RESULT([no]) + fi + AC_SUBST([OCAML_HAS_NATIVE_BYTES]) +]) diff --git a/m4/ac_ocaml_check_safe_string.m4 b/m4/ac_ocaml_check_safe_string.m4 new file mode 100644 index 000000000..712aa7000 --- /dev/null +++ b/m4/ac_ocaml_check_safe_string.m4 @@ -0,0 +1,20 @@ +dnl Copyright (c) 2015 - present Facebook, Inc. +dnl All rights reserved. +dnl +dnl This source code is licensed under the BSD style license found in the +dnl LICENSE file in the root directory of this source tree. An additional grant +dnl of patent rights can be found in the PATENTS file in the same directory. + +AC_DEFUN([AC_OCAMLC_CHECK_SAFE_STRING], +[dnl + OCAMLC_HAS_SAFE_STRING=no + AC_MSG_CHECKING([if $OCAMLC supports the '-safe-string' flag]) + printf "" > conftest.ml + if $OCAMLC -safe-string -c conftest.ml >&5 2>&5 ; then + AC_MSG_RESULT([yes]) + OCAMLC_HAS_SAFE_STRING=yes + else + AC_MSG_RESULT([no]) + fi + AC_SUBST([OCAMLC_HAS_SAFE_STRING]) +])