Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix parsing of integers with leading 0s #982

Merged
merged 16 commits into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions src/base/Literal.ml
Original file line number Diff line number Diff line change
Expand Up @@ -408,16 +408,48 @@ module MkLiteral (T : ScillaType) = struct
let validate_int_string pt x =
let open PrimType in
let open String in
(* Sanitise x before feeding it to of_string. Remove unnecessary sign and leading 0s.
A legal integer matches the regexp [+-]?0*(0|([1-9][0-9]))
"-0" is a special case, so we treat a leading '-' sign separately:

Leading '-': A legal integer matches the regexp -0*(0|([1-9][0-9])).
Remove the 0* part of the string.
Then check if the result is "-0".
If it is, then remove the leading '-'. Otherwise we have the result.

No leading '-': A legal integer matches the regexp +?0*(0|([1-9][0-9])).
Remove the 0* part of the string as well as the '+' sign if it's there.
*)
let x_sanitised =
if String.(sub x ~pos:0 ~len:1 = "-") then
(* Remove unnecessary leading 0s after the sign *)
let x_without_leading_0s =
Str.replace_first (Str.regexp "^-0*\\([0-9]+\\)$") "-\\1" x
in
(* The result may now be -0. If so, then remove the - *)
Str.replace_first (Str.regexp "^-0$") "0" x_without_leading_0s
else
(* Remove unnecessary leading 0s and + sign if it's there *)
Str.replace_first (Str.regexp "^\\+?0*\\([0-9]+\\)$") "\\1" x
in
try
match pt with
| Int_typ Bits32 -> Int32.to_string (Int32.of_string x) = x
| Int_typ Bits64 -> Int64.to_string (Int64.of_string x) = x
| Int_typ Bits128 -> Int128.to_string (Int128.of_string x) = x
| Int_typ Bits256 -> Int256.to_string (Int256.of_string x) = x
| Uint_typ Bits32 -> Uint32.to_string (Uint32.of_string x) = x
| Uint_typ Bits64 -> Uint64.to_string (Uint64.of_string x) = x
| Uint_typ Bits128 -> Uint128.to_string (Uint128.of_string x) = x
| Uint_typ Bits256 -> Uint256.to_string (Uint256.of_string x) = x
| Int_typ Bits32 ->
Int32.to_string (Int32.of_string x_sanitised) = x_sanitised
| Int_typ Bits64 ->
Int64.to_string (Int64.of_string x_sanitised) = x_sanitised
| Int_typ Bits128 ->
Int128.to_string (Int128.of_string x_sanitised) = x_sanitised
| Int_typ Bits256 ->
Int256.to_string (Int256.of_string x_sanitised) = x_sanitised
| Uint_typ Bits32 ->
Uint32.to_string (Uint32.of_string x_sanitised) = x_sanitised
| Uint_typ Bits64 ->
Uint64.to_string (Uint64.of_string x_sanitised) = x_sanitised
| Uint_typ Bits128 ->
Uint128.to_string (Uint128.of_string x_sanitised) = x_sanitised
| Uint_typ Bits256 ->
Uint256.to_string (Uint256.of_string x_sanitised) = x_sanitised
| _ -> false
with _ -> false

Expand Down
1 change: 1 addition & 0 deletions tests/eval/good/Good.ml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ let explist =
"endian_test64.scilexp";
"endian_test128.scilexp";
"endian_test256.scilexp";
"int_lits.scilexp";
]

module Tests = Scilla_test.Util.DiffBasedTests (struct
Expand Down
66 changes: 66 additions & 0 deletions tests/eval/good/gold/int_lits.scilexp.gold
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
(True),
{ [cn3 -> (Int32 0)],
[cn2 -> (Int32 12)],
[cn1 -> (Int32 12)],
[res_c9 -> (Some (Int32 0))],
[c9 -> (String "0")],
[res_c8 -> (None)],
[c8 -> (String "")],
[res_c7 -> (None)],
[c7 -> (String "00001Hello")],
[res_c6 -> (None)],
[c6 -> (String "000000Hello")],
[res_c5 -> (None)],
[c5 -> (String "0Hello")],
[res_c4 -> (None)],
[c4 -> (String "Hello")],
[res_c3 -> (Some (Int32 0))],
[c3 -> (String "00000")],
[res_c2 -> (Some (Int32 123))],
[c2 -> (String "00000123")],
[res_c1 -> (Some (Int32 123))],
[c1 -> (String "123")],
[bn3 -> (Int32 0)],
[bn2 -> (Int32 -12)],
[bn1 -> (Int32 -12)],
[res_b10 -> (None)],
[b10 -> (String "-+0")],
[res_b9 -> (None)],
[b9 -> (String "--0")],
[res_b8 -> (None)],
[b8 -> (String "-")],
[res_b7 -> (None)],
[b7 -> (String "-00001Hello")],
[res_b6 -> (None)],
[b6 -> (String "-000000Hello")],
[res_b5 -> (None)],
[b5 -> (String "-0Hello")],
[res_b4 -> (None)],
[b4 -> (String "-Hello")],
[res_b3 -> (Some (Int32 0))],
[b3 -> (String "-00000")],
[res_b2 -> (Some (Int32 -123))],
[b2 -> (String "-00000123")],
[res_b1 -> (Some (Int32 -123))],
[b1 -> (String "-123")],
[res_a10 -> (None)],
[a10 -> (String "+-0")],
[res_a9 -> (None)],
[a9 -> (String "++0")],
[res_a8 -> (None)],
[a8 -> (String "+")],
[res_a7 -> (None)],
[a7 -> (String "+00001Hello")],
[res_a6 -> (None)],
[a6 -> (String "+000000Hello")],
[res_a5 -> (None)],
[a5 -> (String "+0Hello")],
[res_a4 -> (None)],
[a4 -> (String "+Hello")],
[res_a3 -> (Some (Int32 0))],
[a3 -> (String "+00000")],
[res_a2 -> (Some (Int32 123))],
[a2 -> (String "+00000123")],
[res_a1 -> (Some (Int32 123))],
[a1 -> (String "+123")] }
Gas remaining: 4001019
106 changes: 106 additions & 0 deletions tests/eval/good/int_lits.scilexp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
(* Leading + *)
let a1 = "+123" in
let res_a1 = builtin to_int32 a1 in

let a2 = "+00000123" in
let res_a2 = builtin to_int32 a2 in

let a3 = "+00000" in
let res_a3 = builtin to_int32 a3 in

let a4 = "+Hello" in
let res_a4 = builtin to_int32 a4 in

let a5 = "+0Hello" in
let res_a5 = builtin to_int32 a5 in

let a6 = "+000000Hello" in
let res_a6 = builtin to_int32 a6 in

let a7 = "+00001Hello" in
let res_a7 = builtin to_int32 a7 in

let a8 = "+" in
let res_a8 = builtin to_int32 a8 in

let a9 = "++0" in
let res_a9 = builtin to_int32 a9 in

let a10 = "+-0" in
let res_a10 = builtin to_int32 a10 in

(* let an1 = Int32 +12 in *)
(* let an2 = Int32 +0012 in *)
(* let an3 = Int32 +0 in *)
(* let an4 = Int32 +0000 in *)

(* Leading - *)
let b1 = "-123" in
let res_b1 = builtin to_int32 b1 in

let b2 = "-00000123" in
let res_b2 = builtin to_int32 b2 in

let b3 = "-00000" in
let res_b3 = builtin to_int32 b3 in

let b4 = "-Hello" in
let res_b4 = builtin to_int32 b4 in

let b5 = "-0Hello" in
let res_b5 = builtin to_int32 b5 in

let b6 = "-000000Hello" in
let res_b6 = builtin to_int32 b6 in

let b7 = "-00001Hello" in
let res_b7 = builtin to_int32 b7 in

let b8 = "-" in
let res_b8 = builtin to_int32 b8 in

let b9 = "--0" in
let res_b9 = builtin to_int32 b9 in

let b10 = "-+0" in
let res_b10 = builtin to_int32 b10 in

let bn1 = Int32 -12 in
let bn2 = Int32 -0012 in
let bn3 = Int32 -0 in
let bn3 = Int32 -0000 in

(* Neither leading + nor leading - *)
let c1 = "123" in
let res_c1 = builtin to_int32 c1 in

let c2 = "00000123" in
let res_c2 = builtin to_int32 c2 in

let c3 = "00000" in
let res_c3 = builtin to_int32 c3 in

let c4 = "Hello" in
let res_c4 = builtin to_int32 c4 in

let c5 = "0Hello" in
let res_c5 = builtin to_int32 c5 in

let c6 = "000000Hello" in
let res_c6 = builtin to_int32 c6 in

let c7 = "00001Hello" in
let res_c7 = builtin to_int32 c7 in

let c8 = "" in
let res_c8 = builtin to_int32 c8 in

let c9 = "0" in
let res_c9 = builtin to_int32 c9 in

let cn1 = Int32 12 in
let cn2 = Int32 0012 in
let cn3 = Int32 0 in
let cn3 = Int32 0000 in

True