From 2c3935e04dd8c478845bf5049bcee88a817f0451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 29 Nov 2024 02:17:53 +0100 Subject: [PATCH] Add missing validations in cases where assembly import would silently truncate the value --- libevmasm/Assembly.cpp | 21 ++++++++++++++ .../input.json | 28 +++++++++++++++++++ .../output.json | 11 ++++++++ .../input.json | 28 +++++++++++++++++++ .../output.json | 11 ++++++++ .../input.json | 28 +++++++++++++++++++ .../output.json | 11 ++++++++ .../input.json | 28 +++++++++++++++++++ .../output.json | 11 ++++++++ .../input.json | 28 +++++++++++++++++++ .../output.json | 11 ++++++++ .../input.json | 28 +++++++++++++++++++ .../output.json | 11 ++++++++ .../input.json | 28 +++++++++++++++++++ .../output.json | 11 ++++++++ 15 files changed, 294 insertions(+) create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_bad_hex/input.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_bad_hex/output.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_too_long/input.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_too_long/output.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_sub_size_value/input.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_sub_size_value/output.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_sub_value/input.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_sub_value/output.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_tag_value/input.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_tag_value/output.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_value/input.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_push_value/output.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_tag_value/input.json create mode 100644 test/cmdlineTests/standard_import_asm_json_invalid_tag_value/output.json diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index fdc27241550b..5b86541a6044 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -180,6 +180,17 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json const& _json, std::vector ); }; + auto requireValueInRange = [&](std::string const& _name, std::string const& _value, u256 _min, u256 _max) + { + bigint parsedValue(_value); + solRequire( + _min <= parsedValue && parsedValue <= _max, + AssemblyImportException, + "Value provided for instruction '" + _name + "' is out of the allowed range " + "[" + formatNumber(_min) + ", " + formatNumber(_max) + "]." + ); + }; + solRequire(srcIndex >= -1 && srcIndex < static_cast(_sourceList.size()), AssemblyImportException, "Source index out of bounds."); if (srcIndex != -1) location.sourceName = sharedSourceName(_sourceList[static_cast(srcIndex)]); @@ -217,6 +228,7 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json const& _json, std::vector if (name == "PUSH") { requireValueDefinedForInstruction(name, value); + requireValueInRange(name, "0x" + value, 0, std::numeric_limits::max()); result = {AssemblyItemType::Push, u256("0x" + value)}; } else if (name == "PUSH [ErrorTag]") @@ -227,16 +239,19 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json const& _json, std::vector else if (name == "PUSH [tag]") { requireValueDefinedForInstruction(name, value); + requireValueInRange(name, value, 0, std::numeric_limits::max()); result = {AssemblyItemType::PushTag, updateUsedTags(u256(value))}; } else if (name == "PUSH [$]") { requireValueDefinedForInstruction(name, value); + requireValueInRange(name, "0x" + value, 0, std::numeric_limits::max()); result = {AssemblyItemType::PushSub, u256("0x" + value)}; } else if (name == "PUSH #[$]") { requireValueDefinedForInstruction(name, value); + requireValueInRange(name, "0x" + value, 0, std::numeric_limits::max()); result = {AssemblyItemType::PushSubSize, u256("0x" + value)}; } else if (name == "PUSHSIZE") @@ -267,11 +282,17 @@ AssemblyItem Assembly::createAssemblyItemFromJSON(Json const& _json, std::vector else if (name == "tag") { requireValueDefinedForInstruction(name, value); + requireValueInRange(name, value, 0, std::numeric_limits::max()); result = {AssemblyItemType::Tag, updateUsedTags(u256(value))}; } else if (name == "PUSH data") { requireValueDefinedForInstruction(name, value); + solRequire( + value.size() == 64 && value.find_first_not_of("0123456789abcdefABCDEF") == std::string::npos, + AssemblyImportException, + "Value provided for instruction 'PUSH data' is not a valid 256-bit hexadecimal number." + ); result = {AssemblyItemType::PushData, u256("0x" + value)}; } else if (name == "VERBATIM") diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_bad_hex/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_bad_hex/input.json new file mode 100644 index 000000000000..34dadb702593 --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_bad_hex/input.json @@ -0,0 +1,28 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 0, + "end": 0, + "name": "PUSH data", + "source": 0, + "value": "112233445566778899aabbccddeeff00112233445566778899aabbccddeeffgg" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.bytecode"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_bad_hex/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_bad_hex/output.json new file mode 100644 index 000000000000..c6dce0d9b31b --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_bad_hex/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Assembly import error: Value provided for instruction 'PUSH data' is not a valid 32-bit hash.", + "message": "Assembly import error: Value provided for instruction 'PUSH data' is not a valid 32-bit hash.", + "severity": "error", + "type": "Exception" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_too_long/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_too_long/input.json new file mode 100644 index 000000000000..b92fa0f05ff1 --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_too_long/input.json @@ -0,0 +1,28 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 0, + "end": 0, + "name": "PUSH data", + "source": 0, + "value": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.bytecode"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_too_long/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_too_long/output.json new file mode 100644 index 000000000000..c6dce0d9b31b --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_data_value_too_long/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Assembly import error: Value provided for instruction 'PUSH data' is not a valid 32-bit hash.", + "message": "Assembly import error: Value provided for instruction 'PUSH data' is not a valid 32-bit hash.", + "severity": "error", + "type": "Exception" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_size_value/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_size_value/input.json new file mode 100644 index 000000000000..5e823d4f9be9 --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_size_value/input.json @@ -0,0 +1,28 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 0, + "end": 0, + "name": "PUSH #[$]", + "source": 0, + "value": "10000000000000000" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.bytecode"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_size_value/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_size_value/output.json new file mode 100644 index 000000000000..af9d107f07bb --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_size_value/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Assembly import error: Value provided for instruction 'PUSH #[$]' is out of the allowed range [0, 0xffffffffffffffff].", + "message": "Assembly import error: Value provided for instruction 'PUSH #[$]' is out of the allowed range [0, 0xffffffffffffffff].", + "severity": "error", + "type": "Exception" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_value/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_value/input.json new file mode 100644 index 000000000000..ce3db3e8e2b6 --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_value/input.json @@ -0,0 +1,28 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 0, + "end": 0, + "name": "PUSH [$]", + "source": 0, + "value": "10000000000000000" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.bytecode"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_value/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_value/output.json new file mode 100644 index 000000000000..773fd1451a25 --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_sub_value/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Assembly import error: Value provided for instruction 'PUSH [$]' is out of the allowed range [0, 0xffffffffffffffff].", + "message": "Assembly import error: Value provided for instruction 'PUSH [$]' is out of the allowed range [0, 0xffffffffffffffff].", + "severity": "error", + "type": "Exception" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_tag_value/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_tag_value/input.json new file mode 100644 index 000000000000..6040f575193e --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_tag_value/input.json @@ -0,0 +1,28 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 0, + "end": 0, + "name": "PUSH [tag]", + "source": 0, + "value": "0x100000000" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.bytecode"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_tag_value/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_tag_value/output.json new file mode 100644 index 000000000000..72744ad8045a --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_tag_value/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Assembly import error: Value provided for instruction 'PUSH [tag]' is out of the allowed range [0, 0xffffffff].", + "message": "Assembly import error: Value provided for instruction 'PUSH [tag]' is out of the allowed range [0, 0xffffffff].", + "severity": "error", + "type": "Exception" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_value/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_value/input.json new file mode 100644 index 000000000000..1095d333d16d --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_value/input.json @@ -0,0 +1,28 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 0, + "end": 10, + "name": "PUSH", + "source": 0, + "value": "00112233445566778899001122334455667788990011223344556677889900112233445566778899" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.bytecode"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_push_value/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_push_value/output.json new file mode 100644 index 000000000000..3c18f31caf60 --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_push_value/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Assembly import error: Value provided for instruction 'PUSH' is out of the allowed range [0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff].", + "message": "Assembly import error: Value provided for instruction 'PUSH' is out of the allowed range [0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff].", + "severity": "error", + "type": "Exception" + } + ] +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_tag_value/input.json b/test/cmdlineTests/standard_import_asm_json_invalid_tag_value/input.json new file mode 100644 index 000000000000..ff4eb4d0130f --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_tag_value/input.json @@ -0,0 +1,28 @@ +{ + "language": "EVMAssembly", + "sources": { + "A": { + "assemblyJson": { + ".code": [ + { + "begin": 0, + "end": 0, + "name": "tag", + "source": 0, + "value": "0x100000000" + } + ], + "sourceList": [ + "" + ] + } + } + }, + "settings": { + "outputSelection": { + "*": { + "": ["evm.bytecode"] + } + } + } +} diff --git a/test/cmdlineTests/standard_import_asm_json_invalid_tag_value/output.json b/test/cmdlineTests/standard_import_asm_json_invalid_tag_value/output.json new file mode 100644 index 000000000000..c43b8463824d --- /dev/null +++ b/test/cmdlineTests/standard_import_asm_json_invalid_tag_value/output.json @@ -0,0 +1,11 @@ +{ + "errors": [ + { + "component": "general", + "formattedMessage": "Assembly import error: Value provided for instruction 'tag' is out of the allowed range [0, 0xffffffff].", + "message": "Assembly import error: Value provided for instruction 'tag' is out of the allowed range [0, 0xffffffff].", + "severity": "error", + "type": "Exception" + } + ] +}