Commit c57458ea authored by Benjamin Canou's avatar Benjamin Canou Committed by Grégoire Henry

Michelson: fix inconsistency when reading and printing strings

parent f119a9b2
......@@ -1741,6 +1741,9 @@ language can only be one of the four following constructs.
This simple four cases notation is called Micheline.
The encoding of a Micheline source file must be UTF-8, and non-ASCII
characters can only appear in comments and strings.
Constants
~~~~~~~~~
......@@ -1748,12 +1751,12 @@ There are two kinds of constants:
1. Integers or naturals in decimal (no prefix), hexadecimal (0x prefix),
octal (0o prefix) or binary (0b prefix).
2. Strings with usual escapes ``\n``, ``\t``, ``\b``, ``\r``, ``\\``,
``\"``. The encoding of a Michelson source file must be UTF-8, and
non-ASCII characters can only appear in comments. No line break can
appear in a string. Any non-printable characters must be escaped
using two hexadecimal characters, as in ``\xHH`` or the
predefine escape sequences above..
2. Strings, with usual escape sequences: ``\n``, ``\t``, ``\b``,
``\r``, ``\\``, ``\"``. Unescaped line breaks (both ``\n`` and ``\r``)
cannot appear in the middle of a string.
The current version of Michelson restricts strings to be the printable
subset of 7-bit ASCII, plus the line break ``\n``.
Primitive applications
~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -255,7 +255,7 @@ let tokenize source =
| `Uchar c, stop ->
match uchar_to_char c with
| Some '"' -> skip (tok () :: acc)
| Some '\n' ->
| Some ('\n' | '\r') ->
errors := Unterminated_string { start ; stop } :: !errors ;
skip (tok () :: acc)
| Some '\\' ->
......
......@@ -26,12 +26,13 @@ let print_comment ppf text =
let print_string ppf text =
Format.fprintf ppf "\"" ;
String.iter (function
| '"' | 'r' | 'n' | 't' | 'b' | '\\' as c ->
Format.fprintf ppf "%c" c
| '\x20'..'\x7E' as c ->
Format.fprintf ppf "%c" c
| c ->
Format.fprintf ppf "\\x%02X" (Char.code c))
| '"' -> Format.fprintf ppf "\\\""
| '\n' -> Format.fprintf ppf "\\n"
| '\r' -> Format.fprintf ppf "\\r"
| '\b' -> Format.fprintf ppf "\\b"
| '\t' -> Format.fprintf ppf "\\t"
| '\\' -> Format.fprintf ppf "\\\\"
| c -> Format.fprintf ppf "%c" c)
text ;
Format.fprintf ppf "\""
......
......@@ -1109,8 +1109,16 @@ let rec parse_data
traced (fail (unexpected expr [] Constant_namespace [ D_True ; D_False ]))
(* Strings *)
| String_t, String (_, v) ->
Lwt.return (Gas.consume ctxt (Typecheck_costs.string (String.length v))) >>|? fun ctxt ->
(v, ctxt)
Lwt.return (Gas.consume ctxt (Typecheck_costs.string (String.length v))) >>=? fun ctxt ->
let rec check_printable_ascii i =
if Compare.Int.(i < 0) then true
else match String.get v i with
| '\n' | '\x20'..'\x7E' -> check_printable_ascii (i - 1)
| _ -> false in
if check_printable_ascii (String.length v - 1) then
return (v, ctxt)
else
fail (error ())
| String_t, expr ->
traced (fail (Invalid_kind (location expr, [ String_kind ], kind expr)))
(* Integers *)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment