diff options
-rw-r--r-- | docs/conf.py | 2 | ||||
-rw-r--r-- | docs/control-structures.rst | 4 | ||||
-rw-r--r-- | docs/miscellaneous.rst | 2 | ||||
-rw-r--r-- | docs/security-considerations.rst | 6 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.cpp | 6 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.h | 3 | ||||
-rw-r--r-- | solc/CommandLineInterface.cpp | 16 | ||||
-rw-r--r-- | solc/jsonCompiler.cpp | 16 |
8 files changed, 39 insertions, 16 deletions
diff --git a/docs/conf.py b/docs/conf.py index 8776ec43..d0e26362 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -49,7 +49,7 @@ master_doc = 'index' # General information about the project. project = 'Solidity' -copyright = '2015, Ethereum' +copyright = '2016, Ethereum' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 064996ac..f30a5bdd 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -422,7 +422,7 @@ The opcodes ``pushi`` and ``jumpdest`` cannot be used directly. +-------------------------+------+-----------------------------------------------------------------+ | dup1 ... dup16 | | copy ith stack slot to the top (counting from top) | +-------------------------+------+-----------------------------------------------------------------+ -| swap1 ... swap1 | `*` | swap topmost and ith stack slot below it | +| swap1 ... swap16 | `*` | swap topmost and ith stack slot below it | +-------------------------+------+-----------------------------------------------------------------+ | mload(p) | | mem[p..(p+32)) | +-------------------------+------+-----------------------------------------------------------------+ @@ -661,7 +661,7 @@ variables. Take care that when you assign to variables that point to memory or storage, you will only change the pointer and not the data. There are two kinds of assignments: Functional-style and instruction-style. -For functionaly-style assignments (``variable := value``), you need to provide a value in a +For functional-style assignments (``variable := value``), you need to provide a value in a functional-style expression that results in exactly one stack value and for instruction-style (``=: variable``), the value is just taken from the stack top. For both ways, the colon points to the name of the variable. diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 85fc286c..825be2ce 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -192,7 +192,7 @@ Function Visibility Specifiers - ``public``: visible externally and internally (creates accessor function for storage/state variables) - ``private``: only visible in the current contract -- ``external``: only visible externally (only for functions) - i.e. can only be message-called (via ``this.fun``) +- ``external``: only visible externally (only for functions) - i.e. can only be message-called (via ``this.func``) - ``internal``: only visible internally diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index f1a5dc03..87ee567d 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -146,7 +146,11 @@ Minor Details Furthermore, it is not enforced by the EVM, so a contract function that "claims" to be constant might still cause changes to the state. - Types that do not occupy the full 32 bytes might contain "dirty higher order bits". - This is especially important if you access ``msg.data`` - it poses a malleability risk. + This is especially important if you access ``msg.data`` - it poses a malleability risk: + You can craft transactions that call a function ``f(uint8 x)`` with a raw byte argument + of ``0xff000001`` and with ``0x00000001``. Both are fed to the contract and both will + look like the number ``1`` as far as ``x`` is concerned, but ``msg.data`` will + be different, so if you use ``sha3(msg.data)`` for anything, you will get different results. *************** Recommendations diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index c28e926b..4776a4ce 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -253,9 +253,11 @@ void CompilerStack::link(const std::map<string, h160>& _libraries) } } -bool CompilerStack::prepareFormalAnalysis() +bool CompilerStack::prepareFormalAnalysis(ErrorList* _errors) { - Why3Translator translator(m_errors); + if (!_errors) + _errors = &m_errors; + Why3Translator translator(*_errors); for (Source const* source: m_sourceOrder) if (!translator.process(*source->ast)) return false; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index e111c982..9d2aace4 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -124,8 +124,9 @@ public: void link(std::map<std::string, h160> const& _libraries); /// Tries to translate all source files into a language suitable for formal analysis. + /// @param _errors list to store errors - defaults to the internal error list. /// @returns false on error. - bool prepareFormalAnalysis(); + bool prepareFormalAnalysis(ErrorList* _errors = nullptr); std::string const& formalTranslation() const { return m_formalTranslation; } /// @returns the assembled object for a contract. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 17ab5ba4..09c7c8e8 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -531,17 +531,17 @@ bool CommandLineInterface::processInput() CompilerStack::ReadFileCallback fileReader = [this](string const& _path) { - auto boostPath = boost::filesystem::path(_path); - if (!boost::filesystem::exists(boostPath)) + auto path = boost::filesystem::path(_path); + if (!boost::filesystem::exists(path)) return CompilerStack::ReadFileResult{false, "File not found."}; - boostPath = boost::filesystem::canonical(boostPath); + auto canonicalPath = boost::filesystem::canonical(path); bool isAllowed = false; for (auto const& allowedDir: m_allowedDirectories) { // If dir is a prefix of boostPath, we are fine. if ( - std::distance(allowedDir.begin(), allowedDir.end()) <= std::distance(boostPath.begin(), boostPath.end()) && - std::equal(allowedDir.begin(), allowedDir.end(), boostPath.begin()) + std::distance(allowedDir.begin(), allowedDir.end()) <= std::distance(canonicalPath.begin(), canonicalPath.end()) && + std::equal(allowedDir.begin(), allowedDir.end(), canonicalPath.begin()) ) { isAllowed = true; @@ -550,12 +550,12 @@ bool CommandLineInterface::processInput() } if (!isAllowed) return CompilerStack::ReadFileResult{false, "File outside of allowed directories."}; - else if (!boost::filesystem::is_regular_file(boostPath)) + else if (!boost::filesystem::is_regular_file(canonicalPath)) return CompilerStack::ReadFileResult{false, "Not a valid file."}; else { - auto contents = dev::contentsString(boostPath.string()); - m_sourceCodes[boostPath.string()] = contents; + auto contents = dev::contentsString(canonicalPath.string()); + m_sourceCodes[path.string()] = contents; return CompilerStack::ReadFileResult{true, contents}; } }; diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index e8f674a0..bc1305c5 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -219,6 +219,22 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback output["contracts"][contractName] = contractData; } + // Do not taint the internal error list + ErrorList formalErrors; + if (compiler.prepareFormalAnalysis(&formalErrors)) + output["formal"]["why3"] = compiler.formalTranslation(); + if (!formalErrors.empty()) + { + Json::Value errors(Json::arrayValue); + for (auto const& error: formalErrors) + errors.append(formatError( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error", + scannerFromSourceName + )); + output["formal"]["errors"] = errors; + } + output["sources"] = Json::Value(Json::objectValue); for (auto const& source: _sources) { |