From fe9f8d520cd17e0bf69e6ee507db05fa8a5bf833 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 1 Apr 2020 14:02:30 +0200 Subject: [PATCH] Restrict size for dynamic memory array creation. --- Changelog.md | 4 ++++ libsolidity/codegen/ExpressionCompiler.cpp | 6 +++++ .../array/create_memory_array_too_large.sol | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 test/libsolidity/semanticTests/array/create_memory_array_too_large.sol diff --git a/Changelog.md b/Changelog.md index b512f9eb2..f20b05aa5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,9 @@ ### 0.6.5 (unreleased) +Important Bugfixes: + * Code Generator: Restrict the size of dynamic memory arrays to 64 bits during creation at runtime fixing a possible overflow. + + Language Features: diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 58992426b..fed3751fa 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -995,6 +995,12 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // Fetch requested length. acceptAndConvert(*arguments[0], *TypeProvider::uint256()); + // Make sure we can allocate memory without overflow + m_context << u256(0xffffffffffffffff); + m_context << Instruction::DUP2; + m_context << Instruction::GT; + m_context.appendConditionalRevert(); + // Stack: requested_length utils().fetchFreeMemoryPointer(); diff --git a/test/libsolidity/semanticTests/array/create_memory_array_too_large.sol b/test/libsolidity/semanticTests/array/create_memory_array_too_large.sol new file mode 100644 index 000000000..c42f84862 --- /dev/null +++ b/test/libsolidity/semanticTests/array/create_memory_array_too_large.sol @@ -0,0 +1,24 @@ +contract C { + function f() public returns (uint256) { + uint256 l = 2**256 / 32; + // This used to work without causing an error. + uint256[] memory x = new uint256[](l); + uint256[] memory y = new uint256[](1); + x[1] = 42; + // This used to overwrite the value written above. + y[0] = 23; + return x[1]; + } + function g() public returns (uint256) { + uint256 l = 2**256 / 2 + 1; + // This used to work without causing an error. + uint16[] memory x = new uint16[](l); + uint16[] memory y = new uint16[](1); + x[2] = 42; + // This used to overwrite the value written above. + y[0] = 23; + return x[2]; + }} +// ---- +// f() -> FAILURE +// g() -> FAILURE