mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into breaking
This commit is contained in:
commit
d0551b67d7
@ -466,7 +466,7 @@ jobs:
|
|||||||
<<: *build_ubuntu2004
|
<<: *build_ubuntu2004
|
||||||
environment:
|
environment:
|
||||||
MAKEFLAGS: -j 10
|
MAKEFLAGS: -j 10
|
||||||
CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DSOLC_LINK_STATIC=1 -DUSE_CVC4=OFF -DUSE_Z3=OFF
|
CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: *run_build
|
- run: *run_build
|
||||||
|
@ -22,6 +22,7 @@ if (IS_BIG_ENDIAN)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF)
|
option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF)
|
||||||
|
option(SOLC_STATIC_STDLIBS "Link solc against static versions of libgcc and libstdc++ on supported platforms" OFF)
|
||||||
|
|
||||||
# Setup cccache.
|
# Setup cccache.
|
||||||
include(EthCcache)
|
include(EthCcache)
|
||||||
@ -51,8 +52,27 @@ configure_file("${CMAKE_SOURCE_DIR}/cmake/templates/license.h.in" include/licens
|
|||||||
include(EthOptions)
|
include(EthOptions)
|
||||||
configure_project(TESTS)
|
configure_project(TESTS)
|
||||||
|
|
||||||
find_package(Z3 4.6.0)
|
find_package(Z3 4.8.0)
|
||||||
if (${Z3_FOUND})
|
if(${USE_Z3_DLOPEN})
|
||||||
|
add_definitions(-DHAVE_Z3)
|
||||||
|
add_definitions(-DHAVE_Z3_DLOPEN)
|
||||||
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
|
if(${Z3_FOUND})
|
||||||
|
get_target_property(Z3_HEADER_HINTS z3::libz3 INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
|
endif()
|
||||||
|
find_path(Z3_HEADER_PATH z3.h HINTS ${Z3_HEADER_HINTS})
|
||||||
|
if(Z3_HEADER_PATH)
|
||||||
|
set(Z3_FOUND TRUE)
|
||||||
|
else()
|
||||||
|
message(SEND_ERROR "Dynamic loading of Z3 requires Z3 headers to be present at build time.")
|
||||||
|
endif()
|
||||||
|
if(NOT ${Python3_FOUND})
|
||||||
|
message(SEND_ERROR "Dynamic loading of Z3 requires Python 3 to be present at build time.")
|
||||||
|
endif()
|
||||||
|
if(${SOLC_LINK_STATIC})
|
||||||
|
message(SEND_ERROR "solc cannot be linked statically when dynamically loading Z3.")
|
||||||
|
endif()
|
||||||
|
elseif (${Z3_FOUND})
|
||||||
add_definitions(-DHAVE_Z3)
|
add_definitions(-DHAVE_Z3)
|
||||||
message("Z3 SMT solver found. This enables optional SMT checking with Z3.")
|
message("Z3 SMT solver found. This enables optional SMT checking with Z3.")
|
||||||
endif()
|
endif()
|
||||||
|
@ -45,6 +45,7 @@ Language Features:
|
|||||||
* Wasm backend: Add ``i32.select`` and ``i64.select`` instructions.
|
* Wasm backend: Add ``i32.select`` and ``i64.select`` instructions.
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
* Build System: Optionally support dynamic loading of Z3 and use that mechanism for Linux release builds.
|
||||||
* Code Generator: Avoid memory allocation for default value if it is not used.
|
* Code Generator: Avoid memory allocation for default value if it is not used.
|
||||||
* SMTChecker: Report struct values in counterexamples from CHC engine.
|
* SMTChecker: Report struct values in counterexamples from CHC engine.
|
||||||
* SMTChecker: Support early returns in the CHC engine.
|
* SMTChecker: Support early returns in the CHC engine.
|
||||||
|
@ -209,6 +209,9 @@ endif()
|
|||||||
|
|
||||||
# SMT Solvers integration
|
# SMT Solvers integration
|
||||||
option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON)
|
option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON)
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
option(USE_Z3_DLOPEN "Dynamically load the Z3 SMT solver instead of linking against it." OFF)
|
||||||
|
endif()
|
||||||
option(USE_CVC4 "Allow compiling with CVC4 SMT solver integration" ON)
|
option(USE_CVC4 "Allow compiling with CVC4 SMT solver integration" ON)
|
||||||
|
|
||||||
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||||
|
@ -312,7 +312,7 @@ The following are dependencies for all builds of Solidity:
|
|||||||
+-----------------------------------+-------------------------------------------------------+
|
+-----------------------------------+-------------------------------------------------------+
|
||||||
| `Git`_ | Command-line tool for retrieving source code. |
|
| `Git`_ | Command-line tool for retrieving source code. |
|
||||||
+-----------------------------------+-------------------------------------------------------+
|
+-----------------------------------+-------------------------------------------------------+
|
||||||
| `z3`_ (version 4.6+, Optional) | For use with SMT checker. |
|
| `z3`_ (version 4.8+, Optional) | For use with SMT checker. |
|
||||||
+-----------------------------------+-------------------------------------------------------+
|
+-----------------------------------+-------------------------------------------------------+
|
||||||
| `cvc4`_ (Optional) | For use with SMT checker. |
|
| `cvc4`_ (Optional) | For use with SMT checker. |
|
||||||
+-----------------------------------+-------------------------------------------------------+
|
+-----------------------------------+-------------------------------------------------------+
|
||||||
|
@ -24,10 +24,25 @@ else()
|
|||||||
set(cvc4_SRCS)
|
set(cvc4_SRCS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (${USE_Z3_DLOPEN})
|
||||||
|
file(GLOB Z3_HEADERS ${Z3_HEADER_PATH}/z3*.h)
|
||||||
|
set(Z3_WRAPPER ${CMAKE_CURRENT_BINARY_DIR}/z3wrapper.cpp)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${Z3_WRAPPER}
|
||||||
|
COMMAND ${Python3_EXECUTABLE} genz3wrapper.py ${Z3_HEADERS} > ${Z3_WRAPPER}
|
||||||
|
DEPENDS ${Z3_HEADERS} genz3wrapper.py
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
set(z3_SRCS ${z3_SRCS} ${Z3_WRAPPER} Z3Loader.cpp Z3Loader.h)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(smtutil ${sources} ${z3_SRCS} ${cvc4_SRCS})
|
add_library(smtutil ${sources} ${z3_SRCS} ${cvc4_SRCS})
|
||||||
target_link_libraries(smtutil PUBLIC solutil Boost::boost)
|
target_link_libraries(smtutil PUBLIC solutil Boost::boost)
|
||||||
|
|
||||||
if (${Z3_FOUND})
|
if (${USE_Z3_DLOPEN})
|
||||||
|
target_include_directories(smtutil PUBLIC ${Z3_HEADER_PATH})
|
||||||
|
target_link_libraries(smtutil PUBLIC ${CMAKE_DL_LIBS})
|
||||||
|
elseif (${Z3_FOUND})
|
||||||
target_link_libraries(smtutil PUBLIC z3::libz3)
|
target_link_libraries(smtutil PUBLIC z3::libz3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ SMTPortfolio::SMTPortfolio(
|
|||||||
{
|
{
|
||||||
m_solvers.emplace_back(make_unique<SMTLib2Interface>(move(_smtlib2Responses), move(_smtCallback), m_queryTimeout));
|
m_solvers.emplace_back(make_unique<SMTLib2Interface>(move(_smtlib2Responses), move(_smtCallback), m_queryTimeout));
|
||||||
#ifdef HAVE_Z3
|
#ifdef HAVE_Z3
|
||||||
if (_enabledSolvers.z3)
|
if (_enabledSolvers.z3 && Z3Interface::available())
|
||||||
m_solvers.emplace_back(make_unique<Z3Interface>(m_queryTimeout));
|
m_solvers.emplace_back(make_unique<Z3Interface>(m_queryTimeout));
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CVC4
|
#ifdef HAVE_CVC4
|
||||||
|
@ -21,12 +21,23 @@
|
|||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
|
|
||||||
#include <z3_api.h>
|
#ifdef HAVE_Z3_DLOPEN
|
||||||
|
#include <libsmtutil/Z3Loader.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity::smtutil;
|
using namespace solidity::smtutil;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
|
|
||||||
|
bool Z3Interface::available()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_Z3_DLOPEN
|
||||||
|
return Z3Loader::get().available();
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
Z3Interface::Z3Interface(std::optional<unsigned> _queryTimeout):
|
Z3Interface::Z3Interface(std::optional<unsigned> _queryTimeout):
|
||||||
SolverInterface(_queryTimeout),
|
SolverInterface(_queryTimeout),
|
||||||
m_solver(m_context)
|
m_solver(m_context)
|
||||||
|
@ -30,6 +30,8 @@ class Z3Interface: public SolverInterface, public boost::noncopyable
|
|||||||
public:
|
public:
|
||||||
Z3Interface(std::optional<unsigned> _queryTimeout = {});
|
Z3Interface(std::optional<unsigned> _queryTimeout = {});
|
||||||
|
|
||||||
|
static bool available();
|
||||||
|
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
void push() override;
|
void push() override;
|
||||||
|
70
libsmtutil/Z3Loader.cpp
Normal file
70
libsmtutil/Z3Loader.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#include <libsmtutil/Z3Loader.h>
|
||||||
|
#include <libsmtutil/Exceptions.h>
|
||||||
|
#include <z3.h>
|
||||||
|
#include <z3_version.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace solidity;
|
||||||
|
using namespace solidity::smtutil;
|
||||||
|
|
||||||
|
Z3Loader const& Z3Loader::get()
|
||||||
|
{
|
||||||
|
static Z3Loader z3;
|
||||||
|
return z3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Z3Loader::loadSymbol(char const* _name) const
|
||||||
|
{
|
||||||
|
smtAssert(m_handle, "Attempted to use dynamically loaded Z3, even though it is not available.");
|
||||||
|
void* sym = dlsym(m_handle, _name);
|
||||||
|
smtAssert(sym, string("Symbol \"") + _name + "\" not found in libz3.so");
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Z3Loader::available() const
|
||||||
|
{
|
||||||
|
if (m_handle == nullptr)
|
||||||
|
return false;
|
||||||
|
unsigned major = 0;
|
||||||
|
unsigned minor = 0;
|
||||||
|
unsigned build = 0;
|
||||||
|
unsigned rev = 0;
|
||||||
|
Z3_get_version(&major, &minor, &build, &rev);
|
||||||
|
return major == Z3_MAJOR_VERSION && minor == Z3_MINOR_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
Z3Loader::Z3Loader()
|
||||||
|
{
|
||||||
|
string libname{"libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION)};
|
||||||
|
m_handle = dlmopen(LM_ID_NEWLM, libname.c_str(), RTLD_NOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
Z3Loader::~Z3Loader()
|
||||||
|
{
|
||||||
|
if (m_handle)
|
||||||
|
dlclose(m_handle);
|
||||||
|
}
|
38
libsmtutil/Z3Loader.h
Normal file
38
libsmtutil/Z3Loader.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace solidity::smtutil
|
||||||
|
{
|
||||||
|
|
||||||
|
class Z3Loader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Z3Loader(Z3Loader const&) = delete;
|
||||||
|
Z3Loader& operator=(Z3Loader const&) = delete;
|
||||||
|
static Z3Loader const& get();
|
||||||
|
void* loadSymbol(char const* _name) const;
|
||||||
|
bool available() const;
|
||||||
|
private:
|
||||||
|
Z3Loader();
|
||||||
|
~Z3Loader();
|
||||||
|
void* m_handle = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
99
libsmtutil/genz3wrapper.py
Executable file
99
libsmtutil/genz3wrapper.py
Executable file
@ -0,0 +1,99 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# This file is part of solidity.
|
||||||
|
#
|
||||||
|
# solidity is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# solidity is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with solidity. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Script that generates a dlsym-wrapper for Z3 from the header files.
|
||||||
|
# Expects all Z3 headers as arguments and outputs the wrapper code to stdout.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Patterns to match Z3 API entry point definitions.
|
||||||
|
def_pat = re.compile(" *def_API(.*)")
|
||||||
|
extradef_pat = re.compile(" *extra_API(.*)")
|
||||||
|
# Pattern to extract name and arguments from the above.
|
||||||
|
def_args_pat = re.compile("\('([^']*)'[^\(\)]*\((.*)\)\s*\)")
|
||||||
|
# Pattern to extract a list of arguments from the above.
|
||||||
|
arg_list_pat = re.compile("[^\(]*\([^\)]*\)[, ]*")
|
||||||
|
|
||||||
|
def generateEntryPoint(line, args):
|
||||||
|
m = def_args_pat.match(args)
|
||||||
|
if not m:
|
||||||
|
raise Exception('Could not parse entry point definition: ' + line)
|
||||||
|
name = m.group(1)
|
||||||
|
num_args = len(arg_list_pat.findall(m.group(2)))
|
||||||
|
arglist = ', '.join(f"_{i}" for i in range(num_args))
|
||||||
|
paramlist = ', '.join(f"ArgType<&{name}, {i}> _{i}" for i in range(num_args))
|
||||||
|
print(f'ResultType<&{name}> Z3_API {name}({paramlist})')
|
||||||
|
print('{')
|
||||||
|
print(f'\tstatic auto sym = reinterpret_cast<decltype(&{name})>(Z3Loader::get().loadSymbol(\"{name}\"));')
|
||||||
|
print(f'\treturn sym({arglist});')
|
||||||
|
print('}')
|
||||||
|
|
||||||
|
|
||||||
|
print(r"""// This file is auto-generated from genz3wrapper.py
|
||||||
|
#include <libsmtutil/Z3Loader.h>
|
||||||
|
#include <tuple>
|
||||||
|
#include <z3.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct FunctionTrait;
|
||||||
|
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
struct FunctionTrait<R(*)(Args...)>
|
||||||
|
{
|
||||||
|
using ResultType = R;
|
||||||
|
template<unsigned N>
|
||||||
|
using ArgType = std::tuple_element_t<N, std::tuple<Args...>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<auto F>
|
||||||
|
using ResultType = typename FunctionTrait<decltype(F)>::ResultType;
|
||||||
|
|
||||||
|
template<auto F, unsigned N>
|
||||||
|
using ArgType = typename FunctionTrait<decltype(F)>::template ArgType<N>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace solidity;
|
||||||
|
using namespace solidity::smtutil;
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
void Z3_API Z3_set_error_handler(Z3_context c, Z3_error_handler h)
|
||||||
|
{
|
||||||
|
static auto sym = reinterpret_cast<decltype(&Z3_set_error_handler)>(Z3Loader::get().loadSymbol("Z3_set_error_handler"));
|
||||||
|
sym(c, h);
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
for header in sys.argv[1:]:
|
||||||
|
with open(header, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip('\r\n\t ')
|
||||||
|
m = def_pat.match(line)
|
||||||
|
if m:
|
||||||
|
generateEntryPoint(line, m.group(1).strip('\r\n\t '))
|
||||||
|
m = extradef_pat.match(line)
|
||||||
|
if m:
|
||||||
|
generateEntryPoint(line, m.group(1).strip('\r\n\t '))
|
||||||
|
|
||||||
|
print('}')
|
@ -1437,19 +1437,27 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type)
|
|||||||
{
|
{
|
||||||
solAssert(_type.location() == DataLocation::Storage, "");
|
solAssert(_type.location() == DataLocation::Storage, "");
|
||||||
solAssert(_type.isDynamicallySized(), "");
|
solAssert(_type.isDynamicallySized(), "");
|
||||||
solUnimplementedAssert(!_type.isByteArray(), "Byte Arrays not yet implemented!");
|
|
||||||
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
|
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
|
||||||
|
|
||||||
string functionName = "array_push_zero_" + _type.identifier();
|
string functionName = "array_push_zero_" + _type.identifier();
|
||||||
return m_functionCollector.createFunction(functionName, [&]() {
|
return m_functionCollector.createFunction(functionName, [&]() {
|
||||||
return Whiskers(R"(
|
return Whiskers(R"(
|
||||||
function <functionName>(array) -> slot, offset {
|
function <functionName>(array) -> slot, offset {
|
||||||
let oldLen := <fetchLength>(array)
|
<?isBytes>
|
||||||
if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() }
|
let data := sload(array)
|
||||||
sstore(array, add(oldLen, 1))
|
let oldLen := <extractLength>(data)
|
||||||
|
<increaseBytesSize>(array, data, oldLen, add(oldLen, 1))
|
||||||
|
<!isBytes>
|
||||||
|
let oldLen := <fetchLength>(array)
|
||||||
|
if iszero(lt(oldLen, <maxArrayLength>)) { <panic>() }
|
||||||
|
sstore(array, add(oldLen, 1))
|
||||||
|
</isBytes>
|
||||||
slot, offset := <indexAccess>(array, oldLen)
|
slot, offset := <indexAccess>(array, oldLen)
|
||||||
})")
|
})")
|
||||||
("functionName", functionName)
|
("functionName", functionName)
|
||||||
|
("isBytes", _type.isByteArray())
|
||||||
|
("increaseBytesSize", _type.isByteArray() ? increaseByteArraySizeFunction(_type) : "")
|
||||||
|
("extractLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "")
|
||||||
("panic", panicFunction(PanicCode::ResourceError))
|
("panic", panicFunction(PanicCode::ResourceError))
|
||||||
("fetchLength", arrayLengthFunction(_type))
|
("fetchLength", arrayLengthFunction(_type))
|
||||||
("indexAccess", storageArrayIndexAccessFunction(_type))
|
("indexAccess", storageArrayIndexAccessFunction(_type))
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
|
|
||||||
#include <libsmtutil/SMTPortfolio.h>
|
#include <libsmtutil/SMTPortfolio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_Z3_DLOPEN
|
||||||
|
#include <z3_version.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
@ -83,7 +87,10 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
|
|||||||
m_outerErrorReporter.warning(
|
m_outerErrorReporter.warning(
|
||||||
8084_error,
|
8084_error,
|
||||||
SourceLocation(),
|
SourceLocation(),
|
||||||
"BMC analysis was not possible since no integrated SMT solver (Z3 or CVC4) was found."
|
"BMC analysis was not possible since no SMT solver (Z3 or CVC4) was found."
|
||||||
|
#ifdef HAVE_Z3_DLOPEN
|
||||||
|
" Install libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " to enable Z3."
|
||||||
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,10 @@
|
|||||||
|
|
||||||
#include <boost/range/adaptor/reversed.hpp>
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
|
|
||||||
|
#ifdef HAVE_Z3_DLOPEN
|
||||||
|
#include <z3_version.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -58,7 +62,9 @@ CHC::CHC(
|
|||||||
m_queryTimeout(_timeout)
|
m_queryTimeout(_timeout)
|
||||||
{
|
{
|
||||||
bool usesZ3 = _enabledSolvers.z3;
|
bool usesZ3 = _enabledSolvers.z3;
|
||||||
#ifndef HAVE_Z3
|
#ifdef HAVE_Z3
|
||||||
|
usesZ3 = usesZ3 && Z3Interface::available();
|
||||||
|
#else
|
||||||
usesZ3 = false;
|
usesZ3 = false;
|
||||||
#endif
|
#endif
|
||||||
if (!usesZ3)
|
if (!usesZ3)
|
||||||
@ -88,16 +94,19 @@ void CHC::analyze(SourceUnit const& _source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ranSolver = true;
|
bool ranSolver = true;
|
||||||
#ifndef HAVE_Z3
|
if (auto const* smtLibInterface = dynamic_cast<CHCSmtLib2Interface const*>(m_interface.get()))
|
||||||
ranSolver = dynamic_cast<CHCSmtLib2Interface const*>(m_interface.get())->unhandledQueries().empty();
|
ranSolver = smtLibInterface->unhandledQueries().empty();
|
||||||
#endif
|
|
||||||
if (!ranSolver && !m_noSolverWarning)
|
if (!ranSolver && !m_noSolverWarning)
|
||||||
{
|
{
|
||||||
m_noSolverWarning = true;
|
m_noSolverWarning = true;
|
||||||
m_outerErrorReporter.warning(
|
m_outerErrorReporter.warning(
|
||||||
3996_error,
|
3996_error,
|
||||||
SourceLocation(),
|
SourceLocation(),
|
||||||
|
#ifdef HAVE_Z3_DLOPEN
|
||||||
|
"CHC analysis was not possible since libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " was not found."
|
||||||
|
#else
|
||||||
"CHC analysis was not possible since no integrated z3 SMT solver was found."
|
"CHC analysis was not possible since no integrated z3 SMT solver was found."
|
||||||
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -762,7 +771,7 @@ void CHC::resetSourceAnalysis()
|
|||||||
|
|
||||||
bool usesZ3 = false;
|
bool usesZ3 = false;
|
||||||
#ifdef HAVE_Z3
|
#ifdef HAVE_Z3
|
||||||
usesZ3 = m_enabledSolvers.z3;
|
usesZ3 = m_enabledSolvers.z3 && Z3Interface::available();
|
||||||
if (usesZ3)
|
if (usesZ3)
|
||||||
{
|
{
|
||||||
/// z3::fixedpoint does not have a reset mechanism, so we need to create another.
|
/// z3::fixedpoint does not have a reset mechanism, so we need to create another.
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
#include <libsolidity/formal/ModelChecker.h>
|
#include <libsolidity/formal/ModelChecker.h>
|
||||||
|
#ifdef HAVE_Z3
|
||||||
|
#include <libsmtutil/Z3Interface.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
@ -63,7 +66,7 @@ solidity::smtutil::SMTSolverChoice ModelChecker::availableSolvers()
|
|||||||
{
|
{
|
||||||
smtutil::SMTSolverChoice available = smtutil::SMTSolverChoice::None();
|
smtutil::SMTSolverChoice available = smtutil::SMTSolverChoice::None();
|
||||||
#ifdef HAVE_Z3
|
#ifdef HAVE_Z3
|
||||||
available.z3 = true;
|
available.z3 = solidity::smtutil::Z3Interface::available();
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CVC4
|
#ifdef HAVE_CVC4
|
||||||
available.cvc4 = true;
|
available.cvc4 = true;
|
||||||
|
@ -20,4 +20,9 @@ if(SOLC_LINK_STATIC AND UNIX AND NOT APPLE)
|
|||||||
LINK_SEARCH_START_STATIC ON
|
LINK_SEARCH_START_STATIC ON
|
||||||
LINK_SEARCH_END_STATIC ON
|
LINK_SEARCH_END_STATIC ON
|
||||||
)
|
)
|
||||||
endif()
|
elseif(SOLC_STATIC_STDLIBS AND UNIX AND NOT APPLE)
|
||||||
|
set_target_properties(
|
||||||
|
solc PROPERTIES
|
||||||
|
LINK_FLAGS "-static-libgcc -static-libstdc++"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
@ -821,28 +821,6 @@ BOOST_AUTO_TEST_CASE(constructor)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(blockchain)
|
|
||||||
{
|
|
||||||
char const* sourceCode = R"(
|
|
||||||
contract test {
|
|
||||||
constructor() payable {}
|
|
||||||
function someInfo() public payable returns (uint256 value, address coinbase, uint256 blockNumber) {
|
|
||||||
value = msg.value;
|
|
||||||
coinbase = block.coinbase;
|
|
||||||
blockNumber = block.number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
m_evmcHost->tx_context.block_coinbase = EVMHost::convertToEVMC(h160("0x1212121212121212121212121212121212121212"));
|
|
||||||
m_evmcHost->newBlock();
|
|
||||||
m_evmcHost->newBlock();
|
|
||||||
m_evmcHost->newBlock();
|
|
||||||
m_evmcHost->newBlock();
|
|
||||||
m_evmcHost->newBlock();
|
|
||||||
compileAndRun(sourceCode, 27);
|
|
||||||
ABI_CHECK(callContractFunctionWithValue("someInfo()", 28), encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7));
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(send_ether)
|
BOOST_AUTO_TEST_CASE(send_ether)
|
||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
@ -905,25 +883,6 @@ BOOST_AUTO_TEST_CASE(transfer_ether)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(uncalled_blockhash)
|
|
||||||
{
|
|
||||||
char const* code = R"(
|
|
||||||
contract C {
|
|
||||||
function f() public view returns (bytes32)
|
|
||||||
{
|
|
||||||
return (blockhash)(block.number - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
ALSO_VIA_YUL(
|
|
||||||
DISABLE_EWASM_TESTRUN()
|
|
||||||
compileAndRun(code, 0, "C");
|
|
||||||
bytes result = callContractFunction("f()");
|
|
||||||
BOOST_REQUIRE_EQUAL(result.size(), 32);
|
|
||||||
BOOST_CHECK(result[0] != 0 || result[1] != 0 || result[2] != 0);
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(selfdestruct)
|
BOOST_AUTO_TEST_CASE(selfdestruct)
|
||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
@ -1381,41 +1340,6 @@ BOOST_AUTO_TEST_CASE(contracts_as_addresses)
|
|||||||
BOOST_REQUIRE(callContractFunction("getBalance()") == encodeArgs(u256(20 - 5), u256(5)));
|
BOOST_REQUIRE(callContractFunction("getBalance()") == encodeArgs(u256(20 - 5), u256(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(gaslimit)
|
|
||||||
{
|
|
||||||
char const* sourceCode = R"(
|
|
||||||
contract C {
|
|
||||||
function f() public returns (uint) {
|
|
||||||
return block.gaslimit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
ALSO_VIA_YUL(
|
|
||||||
DISABLE_EWASM_TESTRUN()
|
|
||||||
|
|
||||||
compileAndRun(sourceCode);
|
|
||||||
auto result = callContractFunction("f()");
|
|
||||||
ABI_CHECK(result, encodeArgs(gasLimit()));
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(gasprice)
|
|
||||||
{
|
|
||||||
char const* sourceCode = R"(
|
|
||||||
contract C {
|
|
||||||
function f() public returns (uint) {
|
|
||||||
return tx.gasprice;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
ALSO_VIA_YUL(
|
|
||||||
DISABLE_EWASM_TESTRUN()
|
|
||||||
|
|
||||||
compileAndRun(sourceCode);
|
|
||||||
ABI_CHECK(callContractFunction("f()"), encodeArgs(gasPrice()));
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(blockhash)
|
BOOST_AUTO_TEST_CASE(blockhash)
|
||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
|
@ -22,6 +22,8 @@ contract C {
|
|||||||
return data[0];
|
return data[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// fromMemory() -> 0x00
|
// fromMemory() -> 0x00
|
||||||
// fromCalldata(bytes): 0x40, 0x60, 0x00, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x00
|
// fromCalldata(bytes): 0x40, 0x60, 0x00, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> 0x00
|
||||||
|
@ -18,6 +18,8 @@ contract C {
|
|||||||
return array[index];
|
return array[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// l() -> 0
|
// l() -> 0
|
||||||
// g(uint256): 70 ->
|
// g(uint256): 70 ->
|
||||||
|
11
test/libsolidity/semanticTests/state/block_coinbase.sol
Normal file
11
test/libsolidity/semanticTests/state/block_coinbase.sol
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (address payable) {
|
||||||
|
return block.coinbase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x7878787878787878787878787878787878787878
|
||||||
|
// f() -> 0x7878787878787878787878787878787878787878
|
||||||
|
// f() -> 0x7878787878787878787878787878787878787878
|
11
test/libsolidity/semanticTests/state/block_difficulty.sol
Normal file
11
test/libsolidity/semanticTests/state/block_difficulty.sol
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (uint) {
|
||||||
|
return block.difficulty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 200000000
|
||||||
|
// f() -> 200000000
|
||||||
|
// f() -> 200000000
|
11
test/libsolidity/semanticTests/state/block_gaslimit.sol
Normal file
11
test/libsolidity/semanticTests/state/block_gaslimit.sol
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (uint) {
|
||||||
|
return block.gaslimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 20000000
|
||||||
|
// f() -> 20000000
|
||||||
|
// f() -> 20000000
|
12
test/libsolidity/semanticTests/state/block_number.sol
Normal file
12
test/libsolidity/semanticTests/state/block_number.sol
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
contract C {
|
||||||
|
constructor() {}
|
||||||
|
function f() public returns (uint) {
|
||||||
|
return block.number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// constructor()
|
||||||
|
// f() -> 2
|
||||||
|
// f() -> 3
|
12
test/libsolidity/semanticTests/state/block_timestamp.sol
Normal file
12
test/libsolidity/semanticTests/state/block_timestamp.sol
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
contract C {
|
||||||
|
constructor() {}
|
||||||
|
function f() public returns (uint) {
|
||||||
|
return block.timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// constructor() # This is the 1st block #
|
||||||
|
// f() -> 0x1e # This is the 2nd block (each block is "15 seconds") #
|
||||||
|
// f() -> 0x2d # This is the 3rd block #
|
23
test/libsolidity/semanticTests/state/blockhash_basic.sol
Normal file
23
test/libsolidity/semanticTests/state/blockhash_basic.sol
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
contract C {
|
||||||
|
bytes32 public genesisHash;
|
||||||
|
bytes32 public currentHash;
|
||||||
|
constructor() {
|
||||||
|
require(block.number == 1);
|
||||||
|
genesisHash = blockhash(0);
|
||||||
|
currentHash = blockhash(1);
|
||||||
|
}
|
||||||
|
function f(uint blockNumber) public returns (bytes32) {
|
||||||
|
return blockhash(blockNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// constructor()
|
||||||
|
// genesisHash() -> 0x3737373737373737373737373737373737373737373737373737373737373737
|
||||||
|
// currentHash() -> 0
|
||||||
|
// f(uint256): 0 -> 0x3737373737373737373737373737373737373737373737373737373737373737
|
||||||
|
// f(uint256): 1 -> 0x3737373737373737373737373737373737373737373737373737373737373738
|
||||||
|
// f(uint256): 255 -> 0x00
|
||||||
|
// f(uint256): 256 -> 0x00
|
||||||
|
// f(uint256): 257 -> 0x00
|
11
test/libsolidity/semanticTests/state/gasleft.sol
Normal file
11
test/libsolidity/semanticTests/state/gasleft.sol
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (bool) {
|
||||||
|
return gasleft() > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> true
|
||||||
|
// f() -> true
|
||||||
|
// f() -> true
|
13
test/libsolidity/semanticTests/state/msg_data.sol
Normal file
13
test/libsolidity/semanticTests/state/msg_data.sol
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (bytes calldata) {
|
||||||
|
return msg.data;
|
||||||
|
}
|
||||||
|
function g(uint,bool) public returns (bytes calldata) {
|
||||||
|
return msg.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x20, 4, 17219911917854084299749778639755835327755045716242581057573779540915269926912
|
||||||
|
// g(uint256,bool): 1234, true -> 0x20, 0x44, 35691323728519381642872894128098848782337736632589179916067422734266033766400, 33268574187263889506619096617382224251268236217415066441681855047532544, 26959946667150639794667015087019630673637144422540572481103610249216
|
9
test/libsolidity/semanticTests/state/msg_sender.sol
Normal file
9
test/libsolidity/semanticTests/state/msg_sender.sol
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (address payable) {
|
||||||
|
return msg.sender;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x1212121212121212121212121212120000000012
|
13
test/libsolidity/semanticTests/state/msg_sig.sol
Normal file
13
test/libsolidity/semanticTests/state/msg_sig.sol
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (bytes4) {
|
||||||
|
return msg.sig;
|
||||||
|
}
|
||||||
|
function g() public returns (bytes4) {
|
||||||
|
return msg.sig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x26121ff000000000000000000000000000000000000000000000000000000000
|
||||||
|
// g() -> 0xe2179b8e00000000000000000000000000000000000000000000000000000000
|
10
test/libsolidity/semanticTests/state/msg_value.sol
Normal file
10
test/libsolidity/semanticTests/state/msg_value.sol
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public payable returns (uint) {
|
||||||
|
return msg.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0
|
||||||
|
// f(), 12 ether -> 12000000000000000000
|
11
test/libsolidity/semanticTests/state/tx_gasprice.sol
Normal file
11
test/libsolidity/semanticTests/state/tx_gasprice.sol
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (uint) {
|
||||||
|
return tx.gasprice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 3000000000
|
||||||
|
// f() -> 3000000000
|
||||||
|
// f() -> 3000000000
|
11
test/libsolidity/semanticTests/state/tx_origin.sol
Normal file
11
test/libsolidity/semanticTests/state/tx_origin.sol
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (address payable) {
|
||||||
|
return tx.origin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x9292929292929292929292929292929292929292
|
||||||
|
// f() -> 0x9292929292929292929292929292929292929292
|
||||||
|
// f() -> 0x9292929292929292929292929292929292929292
|
@ -0,0 +1,9 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (bytes32) {
|
||||||
|
return (blockhash)(block.number - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x3737373737373737373737373737373737373737373737373737373737373738
|
16
test/libsolidity/syntaxTests/types/magic_block.sol
Normal file
16
test/libsolidity/syntaxTests/types/magic_block.sol
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public view returns (address payable) {
|
||||||
|
return block.coinbase;
|
||||||
|
}
|
||||||
|
function g() public view returns (uint) {
|
||||||
|
return block.difficulty;
|
||||||
|
}
|
||||||
|
function h() public view returns (uint) {
|
||||||
|
return block.gaslimit;
|
||||||
|
}
|
||||||
|
function i() public view returns (uint) {
|
||||||
|
return block.timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: <istanbul
|
16
test/libsolidity/syntaxTests/types/magic_block_istanbul.sol
Normal file
16
test/libsolidity/syntaxTests/types/magic_block_istanbul.sol
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public view returns (address payable) {
|
||||||
|
return block.coinbase;
|
||||||
|
}
|
||||||
|
function g() public view returns (uint) {
|
||||||
|
return block.difficulty;
|
||||||
|
}
|
||||||
|
function h() public view returns (uint) {
|
||||||
|
return block.gaslimit;
|
||||||
|
}
|
||||||
|
function i() public view returns (uint) {
|
||||||
|
return block.timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=istanbul
|
@ -1,10 +1,98 @@
|
|||||||
#include <test/tools/ossfuzz/protoToAbiV2.h>
|
#include <test/tools/ossfuzz/protoToAbiV2.h>
|
||||||
|
|
||||||
|
#include <boost/preprocessor.hpp>
|
||||||
|
|
||||||
|
/// Convenience macros
|
||||||
|
/// Returns a valid Solidity integer width w such that 8 <= w <= 256.
|
||||||
|
#define INTWIDTH(z, n, _ununsed) BOOST_PP_MUL(BOOST_PP_ADD(n, 1), 8)
|
||||||
|
/// Using declaration that aliases long boost multiprecision types with
|
||||||
|
/// s(u)<width> where <width> is a valid Solidity integer width and "s"
|
||||||
|
/// stands for "signed" and "u" for "unsigned".
|
||||||
|
#define USINGDECL(z, n, sign) \
|
||||||
|
using BOOST_PP_CAT(BOOST_PP_IF(sign, s, u), INTWIDTH(z, n,)) = \
|
||||||
|
boost::multiprecision::number< \
|
||||||
|
boost::multiprecision::cpp_int_backend< \
|
||||||
|
INTWIDTH(z, n,), \
|
||||||
|
INTWIDTH(z, n,), \
|
||||||
|
BOOST_PP_IF( \
|
||||||
|
sign, \
|
||||||
|
boost::multiprecision::signed_magnitude, \
|
||||||
|
boost::multiprecision::unsigned_magnitude \
|
||||||
|
), \
|
||||||
|
boost::multiprecision::unchecked, \
|
||||||
|
void \
|
||||||
|
> \
|
||||||
|
>;
|
||||||
|
/// Instantiate the using declarations for signed and unsigned integer types.
|
||||||
|
BOOST_PP_REPEAT(32, USINGDECL, 1)
|
||||||
|
BOOST_PP_REPEAT(32, USINGDECL, 0)
|
||||||
|
/// Case implementation that returns an integer value of the specified type.
|
||||||
|
/// For signed integers, we divide by two because the range for boost multiprecision
|
||||||
|
/// types is double that of Solidity integer types. Example, 8-bit signed boost
|
||||||
|
/// number range is [-255, 255] but Solidity `int8` range is [-128, 127]
|
||||||
|
#define CASEIMPL(z, n, sign) \
|
||||||
|
case INTWIDTH(z, n,): \
|
||||||
|
stream << BOOST_PP_IF( \
|
||||||
|
sign, \
|
||||||
|
integerValue< \
|
||||||
|
BOOST_PP_CAT( \
|
||||||
|
BOOST_PP_IF(sign, s, u), \
|
||||||
|
INTWIDTH(z, n,) \
|
||||||
|
)>(_counter) / 2, \
|
||||||
|
integerValue< \
|
||||||
|
BOOST_PP_CAT( \
|
||||||
|
BOOST_PP_IF(sign, s, u), \
|
||||||
|
INTWIDTH(z, n,) \
|
||||||
|
)>(_counter) \
|
||||||
|
); \
|
||||||
|
break;
|
||||||
|
/// Switch implementation that instantiates case statements for (un)signed
|
||||||
|
/// Solidity integer types.
|
||||||
|
#define SWITCHIMPL(sign) \
|
||||||
|
ostringstream stream; \
|
||||||
|
switch (_intWidth) \
|
||||||
|
{ \
|
||||||
|
BOOST_PP_REPEAT(32, CASEIMPL, sign) \
|
||||||
|
} \
|
||||||
|
return stream.str();
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity;
|
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::test::abiv2fuzzer;
|
using namespace solidity::test::abiv2fuzzer;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <typename V>
|
||||||
|
static V integerValue(unsigned _counter)
|
||||||
|
{
|
||||||
|
V value = V(
|
||||||
|
u256(solidity::util::keccak256(solidity::util::h256(_counter))) % u256(boost::math::tools::max_value<V>())
|
||||||
|
);
|
||||||
|
if (value % 2 == 0)
|
||||||
|
return value * (-1);
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string signedIntegerValue(unsigned _counter, unsigned _intWidth)
|
||||||
|
{
|
||||||
|
SWITCHIMPL(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static string unsignedIntegerValue(unsigned _counter, unsigned _intWidth)
|
||||||
|
{
|
||||||
|
SWITCHIMPL(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
static string integerValue(unsigned _counter, unsigned _intWidth, bool _signed)
|
||||||
|
{
|
||||||
|
if (_signed)
|
||||||
|
return signedIntegerValue(_counter, _intWidth);
|
||||||
|
else
|
||||||
|
return unsignedIntegerValue(_counter, _intWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string ProtoConverter::getVarDecl(
|
string ProtoConverter::getVarDecl(
|
||||||
string const& _type,
|
string const& _type,
|
||||||
string const& _varName,
|
string const& _varName,
|
||||||
@ -1013,11 +1101,7 @@ string ValueGetterVisitor::visit(BoolType const&)
|
|||||||
|
|
||||||
string ValueGetterVisitor::visit(IntegerType const& _type)
|
string ValueGetterVisitor::visit(IntegerType const& _type)
|
||||||
{
|
{
|
||||||
return integerValueAsString(
|
return integerValue(counter(), getIntWidth(_type), _type.is_signed());
|
||||||
_type.is_signed(),
|
|
||||||
getIntWidth(_type),
|
|
||||||
counter()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string ValueGetterVisitor::visit(FixedByteType const& _type)
|
string ValueGetterVisitor::visit(FixedByteType const& _type)
|
||||||
@ -1041,48 +1125,6 @@ string ValueGetterVisitor::visit(DynamicByteArrayType const& _type)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ValueGetterVisitor::integerValueAsString(bool _sign, unsigned _width, unsigned _counter)
|
|
||||||
{
|
|
||||||
if (_sign)
|
|
||||||
return intValueAsString(_width, _counter);
|
|
||||||
else
|
|
||||||
return uintValueAsString(_width, _counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input(s)
|
|
||||||
* - Unsigned integer to be hashed
|
|
||||||
* - Width of desired uint value
|
|
||||||
* Processing
|
|
||||||
* - Take hash of first parameter and mask it with the max unsigned value for given bit width
|
|
||||||
* Output
|
|
||||||
* - string representation of uint value
|
|
||||||
*/
|
|
||||||
std::string ValueGetterVisitor::uintValueAsString(unsigned _width, unsigned _counter)
|
|
||||||
{
|
|
||||||
solAssert(
|
|
||||||
(_width % 8 == 0),
|
|
||||||
"Proto ABIv2 Fuzzer: Unsigned integer width is not a multiple of 8"
|
|
||||||
);
|
|
||||||
return maskUnsignedIntToHex(_counter, _width/4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input(s)
|
|
||||||
* - counter to be hashed to derive a value for Integer type
|
|
||||||
* - Width of desired int value
|
|
||||||
* Processing
|
|
||||||
* - Take hash of first parameter and mask it with the max signed value for given bit width
|
|
||||||
* Output
|
|
||||||
* - string representation of int value
|
|
||||||
*/
|
|
||||||
std::string ValueGetterVisitor::intValueAsString(unsigned _width, unsigned _counter)
|
|
||||||
{
|
|
||||||
solAssert(
|
|
||||||
(_width % 8 == 0),
|
|
||||||
"Proto ABIv2 Fuzzer: Signed integer width is not a multiple of 8"
|
|
||||||
);
|
|
||||||
return maskUnsignedIntToHex(_counter, ((_width/4) - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ValueGetterVisitor::croppedString(
|
std::string ValueGetterVisitor::croppedString(
|
||||||
unsigned _numBytes,
|
unsigned _numBytes,
|
||||||
unsigned _counter,
|
unsigned _counter,
|
||||||
@ -1153,9 +1195,10 @@ std::string ValueGetterVisitor::fixedByteValueAsString(unsigned _width, unsigned
|
|||||||
|
|
||||||
std::string ValueGetterVisitor::addressValueAsString(unsigned _counter)
|
std::string ValueGetterVisitor::addressValueAsString(unsigned _counter)
|
||||||
{
|
{
|
||||||
return Whiskers(R"(address(<value>))")
|
// TODO: Isabelle encoder expects address literal to be exactly
|
||||||
("value", uintValueAsString(160, _counter))
|
// 20 bytes and a hex string.
|
||||||
.render();
|
// Example: 0x0102030405060708090a0102030405060708090a
|
||||||
|
return "address(" + maskUnsignedIntToHex(_counter, 40) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ValueGetterVisitor::variableLengthValueAsString(
|
std::string ValueGetterVisitor::variableLengthValueAsString(
|
||||||
|
@ -792,9 +792,6 @@ private:
|
|||||||
return m_counter++;
|
return m_counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string intValueAsString(unsigned _width, unsigned _counter);
|
|
||||||
static std::string uintValueAsString(unsigned _width, unsigned _counter);
|
|
||||||
static std::string integerValueAsString(bool _sign, unsigned _width, unsigned _counter);
|
|
||||||
static std::string addressValueAsString(unsigned _counter);
|
static std::string addressValueAsString(unsigned _counter);
|
||||||
static std::string fixedByteValueAsString(unsigned _width, unsigned _counter);
|
static std::string fixedByteValueAsString(unsigned _width, unsigned _counter);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user