aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--Changelog.md1
-rw-r--r--docs/contracts.rst101
-rw-r--r--docs/security-considerations.rst23
-rw-r--r--docs/using-the-compiler.rst21
-rw-r--r--libdevcore/CommonData.h17
-rw-r--r--libjulia/optimiser/README.md61
-rw-r--r--libsolc/CMakeLists.txt9
-rw-r--r--libsolc/libsolc.cpp (renamed from solc/jsonCompiler.cpp)2
-rw-r--r--libsolc/libsolc.h (renamed from solc/jsonCompiler.h)0
-rw-r--r--libsolidity/parsing/Parser.cpp14
-rwxr-xr-xscripts/bytecodecompare/storebytecode.sh2
-rwxr-xr-xscripts/test_emscripten.sh2
-rwxr-xr-xscripts/travis-emscripten/build_emscripten.sh4
-rw-r--r--solc/CMakeLists.txt8
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/fuzzer.cpp2
-rw-r--r--test/libsolidity/JSONCompiler.cpp2
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp6
-rw-r--r--test/libsolidity/SolidityParser.cpp10
20 files changed, 251 insertions, 41 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 105de851..8993f372 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,9 +43,10 @@ configure_project(TESTS)
add_subdirectory(libdevcore)
add_subdirectory(libevmasm)
add_subdirectory(libsolidity)
-add_subdirectory(solc)
+add_subdirectory(libsolc)
if (NOT EMSCRIPTEN)
+ add_subdirectory(solc)
add_subdirectory(liblll)
add_subdirectory(lllc)
endif()
diff --git a/Changelog.md b/Changelog.md
index cf6498a1..4cd83eeb 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -20,6 +20,7 @@ Features:
* Type Checker: More detailed errors for invalid array lengths (such as division by zero).
Bugfixes:
+ * Parser: Disallow event declarations with no parameter list.
### 0.4.18 (2017-10-18)
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 2b0956bb..ca4e79c0 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -426,12 +426,20 @@ value types and strings.
bytes32 constant myHash = keccak256("abc");
}
+.. index:: ! functions
+
+.. _functions:
+
+*********
+Functions
+*********
+
+.. index:: ! view function, function;view
.. _view-functions:
-**************
View Functions
-**************
+==============
Functions can be declared ``view`` in which case they promise not to modify the state.
@@ -465,11 +473,12 @@ The following statements are considered modifying the state:
.. warning::
The compiler does not enforce yet that a ``view`` method is not modifying state.
+.. index:: ! pure function, function;pure
+
.. _pure-functions:
-**************
Pure Functions
-**************
+==============
Functions can be declared ``pure`` in which case they promise not to read from or modify the state.
@@ -498,9 +507,8 @@ In addition to the list of state modifying statements explained above, the follo
.. _fallback-function:
-*****************
Fallback Function
-*****************
+=================
A contract can have exactly one unnamed function. This function cannot have
arguments and cannot return anything.
@@ -577,6 +585,85 @@ Please ensure you test your fallback function thoroughly to ensure the execution
}
}
+.. index:: ! overload
+
+.. _overload-function:
+
+Function Overloading
+====================
+
+A Contract can have multiple functions of the same name but with different arguments.
+This also applies to inherited functions. The following example shows overloading of the
+``f`` function in the scope of contract ``A``.
+
+::
+
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(uint _in) public pure returns (uint out) {
+ out = 1;
+ }
+
+ function f(uint _in, bytes32 _key) public pure returns (uint out) {
+ out = 2;
+ }
+ }
+
+Overloaded functions are also present in the external interface. It is an error if two
+externally visible functions differ by their Solidity types but not by their external types.
+
+::
+
+ // This will not compile
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(B _in) public pure returns (B out) {
+ out = _in;
+ }
+
+ function f(address _in) public pure returns (address out) {
+ out = _in;
+ }
+ }
+
+ contract B {
+ }
+
+
+Both ``f`` function overloads above end up accepting the address type for the ABI although
+they are considered different inside Solidity.
+
+Overload resolution and Argument matching
+-----------------------------------------
+
+Overloaded functions are selected by matching the function declarations in the current scope
+to the arguments supplied in the function call. Functions are selected as overload candidates
+if all arguments can be implicitly converted to the expected types. If there is not exactly one
+candidate, resolution fails.
+
+.. note::
+ Return parameters are not taken into account for overload resolution.
+
+::
+
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(uint8 _in) public pure returns (uint8 out) {
+ out = _in;
+ }
+
+ function f(uint256 _in) public pure returns (uint256 out) {
+ out = _in;
+ }
+ }
+
+Calling ``f(50)`` would create a type error since ``250`` can be implicitly converted both to ``uint8``
+and ``uint256`` types. On another hand ``f(256)`` would resolve to ``f(uint256)`` overload as ``256`` cannot be implicitly
+converted to ``uint8``.
+
.. index:: ! event
.. _events:
@@ -854,7 +941,7 @@ derived override, but this function will bypass
}
If ``Base1`` calls a function of ``super``, it does not simply
-call this function on one of its base contracts. Rather, it
+call this function on one of its base contracts. Rather, it
calls this function on the next base contract in the final
inheritance graph, so it will call ``Base2.kill()`` (note that
the final inheritance sequence is -- starting with the most
diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst
index 337a3d3f..1e2138fa 100644
--- a/docs/security-considerations.rst
+++ b/docs/security-considerations.rst
@@ -69,10 +69,27 @@ complete contract):
}
The problem is not too serious here because of the limited gas as part
-of ``send``, but it still exposes a weakness: Ether transfer always
-includes code execution, so the recipient could be a contract that calls
+of ``send``, but it still exposes a weakness: Ether transfer can always
+include code execution, so the recipient could be a contract that calls
back into ``withdraw``. This would let it get multiple refunds and
-basically retrieve all the Ether in the contract.
+basically retrieve all the Ether in the contract. In particular, the
+following contract will allow an attacker to refund multiple times
+as it uses ``call`` which forwards all remaining gas by default:
+
+::
+
+ pragma solidity ^0.4.0;
+
+ // THIS CONTRACT CONTAINS A BUG - DO NOT USE
+ contract Fund {
+ /// Mapping of ether shares of the contract.
+ mapping(address => uint) shares;
+ /// Withdraw your share.
+ function withdraw() {
+ if (msg.sender.call.value(shares[msg.sender])())
+ shares[msg.sender] = 0;
+ }
+ }
To avoid re-entrancy, you can use the Checks-Effects-Interactions pattern as
outlined further below:
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
index c12750c8..f1f13b82 100644
--- a/docs/using-the-compiler.rst
+++ b/docs/using-the-compiler.rst
@@ -177,7 +177,8 @@ Output Description
start: 0,
end: 100
],
- // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc
+ // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc.
+ // See below for complete list of types.
type: "TypeError",
// Mandatory: Component where the error originated, such as "general", "ewasm", etc.
component: "general",
@@ -273,3 +274,21 @@ Output Description
}
}
}
+
+
+Error types
+~~~~~~~~~~~
+
+1. ``JSONError``: JSON input doesn't conform to the required format, e.g. input is not a JSON object, the language is not supported, etc.
+2. ``IOError``: IO and import processing errors, such as unresolvable URL or hash mismatch in supplied sources.
+3. ``ParserError``: Source code doesn't conform to the language rules.
+4. ``DocstringParsingError``: The NatSpec tags in the comment block cannot be parsed.
+5. ``SyntaxError``: Syntactical error, such as ``continue`` is used outside of a ``for`` loop.
+6. ``DeclarationError``: Invalid, unresolvable or clashing identifier names. e.g. ``Identifier not found``
+7. ``TypeError``: Error within the type system, such as invalid type conversions, invalid assignments, etc.
+8. ``UnimplementedFeatureError``: Feature is not supported by the compiler, but is expected to be supported in future versions.
+9. ``InternalCompilerError``: Internal bug triggered in the compiler - this should be reported as an issue.
+10. ``Exception``: Unknown failure during compilation - this should be reported as an issue.
+11. ``CompilerError``: Invalid use of the compiler stack - this should be reported as an issue.
+12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue.
+13. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible.
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index e76a0949..b85abe95 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -183,6 +183,12 @@ template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U con
_a.push_back(i);
return _a;
}
+/// Concatenate the contents of a container onto a vector, move variant.
+template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U&& _b)
+{
+ std::move(_b.begin(), _b.end(), std::back_inserter(_a));
+ return _a;
+}
/// Concatenate the contents of a container onto a set
template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U const& _b)
{
@@ -197,6 +203,17 @@ inline std::vector<T> operator+(std::vector<T> const& _a, std::vector<T> const&
ret += _b;
return ret;
}
+/// Concatenate two vectors of elements, moving them.
+template <class T>
+inline std::vector<T> operator+(std::vector<T>&& _a, std::vector<T>&& _b)
+{
+ std::vector<T> ret(std::move(_a));
+ if (&_a == &_b)
+ ret += ret;
+ else
+ ret += std::move(_b);
+ return ret;
+}
template <class T, class V>
bool contains(T const& _t, V const& _v)
diff --git a/libjulia/optimiser/README.md b/libjulia/optimiser/README.md
new file mode 100644
index 00000000..771cb707
--- /dev/null
+++ b/libjulia/optimiser/README.md
@@ -0,0 +1,61 @@
+## IULIA Optimiser
+
+The iulia optimiser consists of several stages and components that all transform
+the AST in a semantically equivalent way. The goal is to end up either with code
+that is shorter or at least only marginally longer but will allow further
+optimisation steps.
+
+The optimiser currently follows a purely greedy strategy and does not do any
+backtracking.
+
+## Disambiguator
+
+The disambiguator takes an AST and returns a fresh copy where all identifiers have
+names unique to the input AST. This is a prerequisite for all other optimiser stages.
+One of the benefits is that identifier lookup does not need to take scopes into account
+and we can basically ignore the result of the analysis phase.
+
+All subsequent stages have the property that all names stay unique. This means if
+a new identifier needs to be introduced, a new unique name is generated.
+
+## Function Hoister
+
+The function hoister moves all function definitions to the topmost block. This is
+a semantically equivalent transformation as long as it is performed after the
+disambiguation stage. The reason is that moving a definition upwards cannot decrease
+its visibility and it is impossible to reference variables defined in a different function.
+
+The benefit of this stage is that function definitions can be lookup up more easily.
+
+## Function Grouper
+
+The function grouper has to be applied after the disambiguator and the function hoister.
+Its effect is that all topmost elements that are not function definitions are moved
+into a single block which is the first satement of the root block.
+
+After this step, a program has the following normal form:
+
+ { I F... }
+
+Where I is a block that does not contain any function definitions (not even recursively)
+and F is a list of function definitions such that no function contains a function definition.
+
+## Functional Inliner
+
+The functional inliner depends on the disambiguator, the function hoister and function grouper.
+It performs function inlining such that the result of the inlining is an expression. This can
+only be done if the body of the function to be inlined has the form ``{ r := E }`` where ``r``
+is the single return value of the function, ``E`` is an expression and all arguments in the
+function call are so-called movable expressions. A movable expression is either a literal, a
+variable or a function call (or EVM opcode) which does not have side-effects and also does not
+depend on any side-effects.
+
+As an example, neither ``mload`` nor ``mstore`` would be allowed.
+
+## Full Function Inliner
+
+## Variable Eliminator
+
+## Unused Declaration Pruner
+
+## Function Unifier
diff --git a/libsolc/CMakeLists.txt b/libsolc/CMakeLists.txt
new file mode 100644
index 00000000..e67583dd
--- /dev/null
+++ b/libsolc/CMakeLists.txt
@@ -0,0 +1,9 @@
+if (EMSCRIPTEN)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='[\"_compileJSON\",\"_license\",\"_version\",\"_compileJSONMulti\",\"_compileJSONCallback\",\"_compileStandard\"]' -s RESERVED_FUNCTION_POINTERS=20")
+ add_executable(soljson libsolc.cpp)
+ target_link_libraries(soljson PRIVATE solidity)
+else()
+ add_library(libsolc libsolc.cpp)
+ set_target_properties(libsolc PROPERTIES OUTPUT_NAME solc)
+ target_link_libraries(libsolc PRIVATE solidity)
+endif()
diff --git a/solc/jsonCompiler.cpp b/libsolc/libsolc.cpp
index 23feaa2a..3a6e1521 100644
--- a/solc/jsonCompiler.cpp
+++ b/libsolc/libsolc.cpp
@@ -20,7 +20,7 @@
* JSON interface for the solidity compiler to be used from Javascript.
*/
-#include <solc/jsonCompiler.h>
+#include <libsolc/libsolc.h>
#include <libdevcore/Common.h>
#include <libdevcore/JSON.h>
#include <libsolidity/interface/StandardCompiler.h>
diff --git a/solc/jsonCompiler.h b/libsolc/libsolc.h
index c392ce93..c392ce93 100644
--- a/solc/jsonCompiler.h
+++ b/libsolc/libsolc.h
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 821e81d2..05b877b5 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -644,15 +644,11 @@ ASTPointer<EventDefinition> Parser::parseEventDefinition()
expectToken(Token::Event);
ASTPointer<ASTString> name(expectIdentifierToken());
- ASTPointer<ParameterList> parameters;
- if (m_scanner->currentToken() == Token::LParen)
- {
- VarDeclParserOptions options;
- options.allowIndexed = true;
- parameters = parseParameterList(options);
- }
- else
- parameters = createEmptyParameterList();
+
+ VarDeclParserOptions options;
+ options.allowIndexed = true;
+ ASTPointer<ParameterList> parameters = parseParameterList(options);
+
bool anonymous = false;
if (m_scanner->currentToken() == Token::Anonymous)
{
diff --git a/scripts/bytecodecompare/storebytecode.sh b/scripts/bytecodecompare/storebytecode.sh
index 8d4100bf..557e3275 100755
--- a/scripts/bytecodecompare/storebytecode.sh
+++ b/scripts/bytecodecompare/storebytecode.sh
@@ -40,7 +40,7 @@ TMPDIR=$(mktemp -d)
if [[ "$SOLC_EMSCRIPTEN" = "On" ]]
then
- cp "$REPO_ROOT/build/solc/soljson.js" .
+ cp "$REPO_ROOT/build/libsolc/soljson.js" .
npm install solc
cat > solc <<EOF
#!/usr/bin/env node
diff --git a/scripts/test_emscripten.sh b/scripts/test_emscripten.sh
index 4996e957..b659e5e5 100755
--- a/scripts/test_emscripten.sh
+++ b/scripts/test_emscripten.sh
@@ -29,7 +29,7 @@
set -e
REPO_ROOT=$(cd $(dirname "$0")/.. && pwd)
-SOLJSON="$REPO_ROOT/build/solc/soljson.js"
+SOLJSON="$REPO_ROOT/build/libsolc/soljson.js"
DIR=$(mktemp -d)
(
diff --git a/scripts/travis-emscripten/build_emscripten.sh b/scripts/travis-emscripten/build_emscripten.sh
index bf460e8e..56826997 100755
--- a/scripts/travis-emscripten/build_emscripten.sh
+++ b/scripts/travis-emscripten/build_emscripten.sh
@@ -87,8 +87,8 @@ make -j 4
cd ..
mkdir -p upload
-cp build/solc/soljson.js upload/
-cp build/solc/soljson.js ./
+cp build/libsolc/soljson.js upload/
+cp build/libsolc/soljson.js ./
OUTPUT_SIZE=`ls -la soljson.js`
diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt
index 656b27c3..d9b12a06 100644
--- a/solc/CMakeLists.txt
+++ b/solc/CMakeLists.txt
@@ -10,14 +10,6 @@ target_link_libraries(solc PRIVATE solidity ${Boost_PROGRAM_OPTIONS_LIBRARIES})
include(GNUInstallDirs)
install(TARGETS solc DESTINATION "${CMAKE_INSTALL_BINDIR}")
-if (EMSCRIPTEN)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='[\"_compileJSON\",\"_license\",\"_version\",\"_compileJSONMulti\",\"_compileJSONCallback\",\"_compileStandard\"]' -s RESERVED_FUNCTION_POINTERS=20")
- add_executable(soljson jsonCompiler.cpp)
-else()
- add_library(soljson jsonCompiler.cpp)
-endif()
-target_link_libraries(soljson PRIVATE solidity)
-
if(SOLC_LINK_STATIC AND UNIX AND NOT APPLE)
# Produce solc as statically linked binary (includes C/C++ standard libraries)
# This is not supported on macOS, see
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 6a8a4399..f36ad4c5 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -3,7 +3,7 @@ list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/fuzzer.cpp")
file(GLOB_RECURSE headers "*.h")
add_executable(soltest ${sources} ${headers})
-target_link_libraries(soltest PRIVATE soljson solidity lll evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
+target_link_libraries(soltest PRIVATE libsolc solidity lll evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
add_executable(solfuzzer fuzzer.cpp)
-target_link_libraries(solfuzzer soljson evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES})
+target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES})
diff --git a/test/fuzzer.cpp b/test/fuzzer.cpp
index 53ba7201..578e63a4 100644
--- a/test/fuzzer.cpp
+++ b/test/fuzzer.cpp
@@ -20,7 +20,7 @@
#include <libevmasm/Assembly.h>
#include <libevmasm/ConstantOptimiser.h>
-#include <solc/jsonCompiler.h>
+#include <libsolc/libsolc.h>
#include <json/json.h>
diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp
index 7dc4808b..0c904c77 100644
--- a/test/libsolidity/JSONCompiler.cpp
+++ b/test/libsolidity/JSONCompiler.cpp
@@ -23,7 +23,7 @@
#include <boost/test/unit_test.hpp>
#include <libdevcore/JSON.h>
#include <libsolidity/interface/Version.h>
-#include <solc/jsonCompiler.h>
+#include <libsolc/libsolc.h>
#include "../Metadata.h"
#include "../TestHelper.h"
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 05dc9ba3..f5f7e64a 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -2971,7 +2971,7 @@ BOOST_AUTO_TEST_CASE(event_no_arguments)
{
char const* sourceCode = R"(
contract ClientReceipt {
- event Deposit;
+ event Deposit();
function deposit() {
Deposit();
}
@@ -3013,7 +3013,7 @@ BOOST_AUTO_TEST_CASE(events_with_same_name)
{
char const* sourceCode = R"(
contract ClientReceipt {
- event Deposit;
+ event Deposit();
event Deposit(address _addr);
event Deposit(address _addr, uint _amount);
function deposit() returns (uint) {
@@ -3059,7 +3059,7 @@ BOOST_AUTO_TEST_CASE(events_with_same_name_inherited)
{
char const* sourceCode = R"(
contract A {
- event Deposit;
+ event Deposit();
}
contract B {
diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp
index 72473c3e..861e6408 100644
--- a/test/libsolidity/SolidityParser.cpp
+++ b/test/libsolidity/SolidityParser.cpp
@@ -960,6 +960,16 @@ BOOST_AUTO_TEST_CASE(event_arguments_indexed)
BOOST_CHECK(successParse(text));
}
+BOOST_AUTO_TEST_CASE(event_with_no_argument_list_fails)
+{
+ char const* text = R"(
+ contract c {
+ event e;
+ }
+ )";
+ CHECK_PARSE_ERROR(text, "Expected token LParen got 'Semicolon'");
+}
+
BOOST_AUTO_TEST_CASE(visibility_specifiers)
{
char const* text = R"(