From 7f54733d6e2a39f37fdf249037da685b9328bfb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Bilge=20Yal=C3=A7=C4=B1nkaya?= Date: Tue, 1 Aug 2023 19:23:34 +0200 Subject: [PATCH] `smallInt*` unhandled cases (#116) * smallIntGetUnsignedArgument handle index error * split rules with if-then-else --- tests/simple/bad-bounds.wast | 87 ++++++++++++++++++++++++++++++++++++ vmhooks/smallIntOps.md | 45 +++++++++++++++---- 2 files changed, 123 insertions(+), 9 deletions(-) diff --git a/tests/simple/bad-bounds.wast b/tests/simple/bad-bounds.wast index 1e4cc32b..a59918bd 100644 --- a/tests/simple/bad-bounds.wast +++ b/tests/simple/bad-bounds.wast @@ -10,6 +10,18 @@ deployTx( (import "env" "getCaller" (func $getCaller (param i32))) (import "env" "isSmartContract" (func $isSmartContract (param i32) (result i32))) (import "env" "writeEventLog" (func $writeEventLog (param i32 i32 i32 i32 i32))) + + (import "env" "smallIntGetUnsignedArgument" + (func $smallIntGetUnsignedArgument (param i32) (result i64)) + ) + + (import "env" "smallIntGetSignedArgument" + (func $smallIntGetSignedArgument (param i32) (result i64)) + ) + + (import "env" "smallIntFinishUnsigned" (func $smallIntFinishUnsigned (param i64))) + (import "env" "smallIntFinishSigned" (func $smallIntFinishSigned (param i64))) + (func (export "memStoreNegativeOffset") i32.const -1 call $getCaller @@ -34,6 +46,21 @@ deployTx( i32.const 0 call $writeEventLog ) + + (func (export "smallIntGetUnsignedArgumentTest") + (call $smallIntGetSignedArgument (i32.const 0)) ;; read the first argument: i + i32.wrap_i64 + call $smallIntGetUnsignedArgument ;; read the ith argument + call $smallIntFinishUnsigned ;; return it + ) + + (func (export "smallIntGetSignedArgumentTest") + (call $smallIntGetSignedArgument (i32.const 0)) ;; read the first argument: i + i32.wrap_i64 + call $smallIntGetSignedArgument ;; read the ith argument + call $smallIntFinishSigned ;; return it + ) + (func (export "init")) (memory (;0;) 17) (export "memory" (memory 0)) @@ -105,4 +132,64 @@ callTx( checkExpectStatus(ExecutionFailed) checkExpectMessage(b"negative numArguments") +;; pass 2 arguments, get 2nd +callTx( + "testCaller" + , "testContract" + , 0, .List + , "smallIntGetUnsignedArgumentTest" + , ListItem(Int2Bytes(1, BE, Signed)) ListItem(Int2Bytes(123, BE, Unsigned)) + , 0 + , 0 +) + +checkExpectStatus(OK) +checkExpectOut(ListItem(Int2Bytes(123, BE, Unsigned))) + + +;; pass 1 argument, get 2nd, should fail +callTx( + "testCaller" + , "testContract" + , 0, .List + , "smallIntGetUnsignedArgumentTest" + , ListItem(Int2Bytes(1, BE, Signed)) + , 0 + , 0 +) + +checkExpectStatus(ExecutionFailed) +checkExpectMessage(b"argument index out of range") + + +;; pass 2 arguments, get -1st, should fail +callTx( + "testCaller" + , "testContract" + , 0, .List + , "smallIntGetUnsignedArgumentTest" + , ListItem(Int2Bytes(-1, BE, Signed)) ListItem(Int2Bytes(123, BE, Unsigned)) + , 0 + , 0 +) + +checkExpectStatus(ExecutionFailed) +checkExpectMessage(b"argument index out of range") + + +;; pass 2 arguments (2nd is too big for u64), get 2nd, should fail +callTx( + "testCaller" + , "testContract" + , 0, .List + , "smallIntGetUnsignedArgumentTest" + , ListItem(Int2Bytes(1, BE, Signed)) + ListItem(Int2Bytes(maxUInt64 +Int 5, BE, Unsigned)) + , 0 + , 0 +) + +checkExpectStatus(UserError) +checkExpectMessage(b"argument out of range") + setExitCode 0 diff --git a/vmhooks/smallIntOps.md b/vmhooks/smallIntOps.md index 45642399..fca7be7d 100644 --- a/vmhooks/smallIntOps.md +++ b/vmhooks/smallIntOps.md @@ -9,20 +9,47 @@ require "../elrond-config.md" module SMALLINTOPS imports BASEOPS imports ELROND-CONFIG + imports private LIST-BYTES-EXTENSIONS // extern long long smallIntGetUnsignedArgument(void *context, int32_t id); - rule hostCall("env", "smallIntGetUnsignedArgument", [ i32 .ValTypes ] -> [ i64 .ValTypes ]) - => #returnIfUInt64(Bytes2Int(ARGS[ARG_IDX], BE, Unsigned), "argument out of range") ... - 0 |-> ARG_IDX - ARGS + rule [smallIntGetUnsignedArgument]: + hostCall("env", "smallIntGetUnsignedArgument", [ i32 .ValTypes ] -> [ i64 .ValTypes ]) + => #returnIfUInt64(Bytes2Int(ARGS[ARG_IDX] orDefault b"", BE, Unsigned), "argument out of range") + ... + + 0 |-> ARG_IDX + ARGS requires #validArgIdx(ARG_IDX, ARGS) + rule [smallIntGetUnsignedArgument-ioor]: + hostCall("env", "smallIntGetUnsignedArgument", [ i32 .ValTypes ] -> [ i64 .ValTypes ]) + => #throwException(ExecutionFailed, "argument index out of range") + ... + + 0 |-> ARG_IDX + ARGS + requires notBool #validArgIdx(ARG_IDX, ARGS) + + // extern long long smallIntGetSignedArgument(void *context, int32_t id); - rule hostCall("env", "smallIntGetSignedArgument", [ i32 .ValTypes ] -> [ i64 .ValTypes ]) - => #returnIfSInt64(Bytes2Int(ARGS[ARG_IDX], BE, Signed), "argument out of range") ... - 0 |-> ARG_IDX - ARGS - requires ARG_IDX hostCall("env", "smallIntGetSignedArgument", [ i32 .ValTypes ] -> [ i64 .ValTypes ]) + => #returnIfSInt64(Bytes2Int(ARGS[ARG_IDX] orDefault b"", BE, Signed), "argument out of range") + ... + + 0 |-> ARG_IDX + ARGS + requires #validArgIdx(ARG_IDX, ARGS) + + rule [smallIntGetSignedArgument-ioor]: + hostCall("env", "smallIntGetSignedArgument", [ i32 .ValTypes ] -> [ i64 .ValTypes ]) + => #throwException(ExecutionFailed, "argument index out of range") + ... + + 0 |-> ARG_IDX + ARGS + requires notBool #validArgIdx(ARG_IDX, ARGS) + // extern void smallIntFinishUnsigned(void* context, long long value); rule hostCall("env", "smallIntFinishUnsigned", [ i64 .ValTypes ] -> [ .ValTypes ])