From 1e280e56d1f0ecf5edd6482e95f9e4a3d3726f94 Mon Sep 17 00:00:00 2001 From: Christophe Troestler Date: Thu, 23 Nov 2017 19:25:45 +0100 Subject: [PATCH 1/2] Escape double quotes for META field values Fixes https://github.com/janestreet/jbuilder/issues/331 --- src/meta.ml | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/meta.ml b/src/meta.ml index 610d73c3..399744dd 100644 --- a/src/meta.ml +++ b/src/meta.ml @@ -236,13 +236,37 @@ let pp_list f ppf l = Format.pp_print_cut ppf (); f ppf x) +let escape_double_quote s = + let n = ref 0 in + let len = String.length s in + for i = 0 to len - 1 do + if String.unsafe_get s i = '"' then incr n; + done; + if !n = 0 then s + else ( + let b = Bytes.create (len + !n) in + n := 0; + for i = 0 to len - 1 do + if String.unsafe_get s i = '"' then ( + Bytes.unsafe_set b !n '\\'; + incr n; + ); + Bytes.unsafe_set b !n (String.unsafe_get s i); + incr n + done; + Bytes.unsafe_to_string b + ) + +let pp_print_text fmt s = Format.pp_print_text fmt (escape_double_quote s) +let pp_print_string fmt s = Format.pp_print_string fmt (escape_double_quote s) + let pp_value var = match var with | "archive" | "plugin" | "requires" | "ppx_runtime_deps" | "linkopts" | "jsoo_runtime" -> - Format.pp_print_text + pp_print_text | _ -> - Format.pp_print_string + pp_print_string let rec pp ppf entries = Format.fprintf ppf "@[%a@]" (pp_list pp_entry) entries From d8a39b66ded69f587d685f3ff2859eb1c77924c6 Mon Sep 17 00:00:00 2001 From: Christophe Troestler Date: Fri, 24 Nov 2017 16:08:34 +0100 Subject: [PATCH 2/2] Move escape_double_quote to Import.String & refactor --- src/import.ml | 24 ++++++++++++++++++++++++ src/meta.ml | 40 +++++++++++++--------------------------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/import.ml b/src/import.ml index a45d231c..40059e43 100644 --- a/src/import.ml +++ b/src/import.ml @@ -306,6 +306,30 @@ module String = struct loop i (j + 1) ~last_is_cr:false in loop 0 0 ~last_is_cr:false + + (* Escape ONLY double quotes. String.escape also escapes + '\n',... and transforms all chars above '~' into '\xxx' which is + not suitable for UTF-8 strings. *) + let escape_double_quote s = + let n = ref 0 in + let len = String.length s in + for i = 0 to len - 1 do + if String.unsafe_get s i = '"' then incr n; + done; + if !n = 0 then s + else ( + let b = Bytes.create (len + !n) in + n := 0; + for i = 0 to len - 1 do + if String.unsafe_get s i = '"' then ( + Bytes.unsafe_set b !n '\\'; + incr n; + ); + Bytes.unsafe_set b !n (String.unsafe_get s i); + incr n + done; + Bytes.unsafe_to_string b + ) end module Sys = struct diff --git a/src/meta.ml b/src/meta.ml index 399744dd..f5e1dbea 100644 --- a/src/meta.ml +++ b/src/meta.ml @@ -236,31 +236,17 @@ let pp_list f ppf l = Format.pp_print_cut ppf (); f ppf x) -let escape_double_quote s = - let n = ref 0 in - let len = String.length s in - for i = 0 to len - 1 do - if String.unsafe_get s i = '"' then incr n; - done; - if !n = 0 then s - else ( - let b = Bytes.create (len + !n) in - n := 0; - for i = 0 to len - 1 do - if String.unsafe_get s i = '"' then ( - Bytes.unsafe_set b !n '\\'; - incr n; - ); - Bytes.unsafe_set b !n (String.unsafe_get s i); - incr n - done; - Bytes.unsafe_to_string b - ) +let pp_print_text ppf s = + Format.fprintf ppf "\"@["; + Format.pp_print_text ppf (String.escape_double_quote s); + Format.fprintf ppf "@]\"" -let pp_print_text fmt s = Format.pp_print_text fmt (escape_double_quote s) -let pp_print_string fmt s = Format.pp_print_string fmt (escape_double_quote s) +let pp_print_string ppf s = + Format.fprintf ppf "\"@["; + Format.pp_print_string ppf (String.escape_double_quote s); + Format.fprintf ppf "@]\"" -let pp_value var = +let pp_quoted_value var = match var with | "archive" | "plugin" | "requires" | "ppx_runtime_deps" | "linkopts" | "jsoo_runtime" -> @@ -277,12 +263,12 @@ and pp_entry ppf entry = | Comment s -> fprintf ppf "# %s" s | Rule { var; predicates = []; action; value } -> - fprintf ppf "@[%s %s \"@[%a@]\"@]" - var (string_of_action action) (pp_value var) value + fprintf ppf "@[%s %s %a@]" + var (string_of_action action) (pp_quoted_value var) value | Rule { var; predicates; action; value } -> - fprintf ppf "@[%s(%s) %s \"@[%a@]\"@]" + fprintf ppf "@[%s(%s) %s %a@]" var (String.concat ~sep:"," (List.map predicates ~f:string_of_predicate)) - (string_of_action action) (pp_value var) value + (string_of_action action) (pp_quoted_value var) value | Package { name; entries } -> fprintf ppf "@[package %S (@,%a@]@,)" name pp entries