Merge pull request #10228 from ethereum/issue-9565

Detect circular references for library and free functions
This commit is contained in:
chriseth 2021-03-30 23:49:22 +02:00 committed by GitHub
commit 851051c64a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1168 additions and 288 deletions

View File

@ -6,6 +6,7 @@ Language Features:
Compiler Features:
* Analysis: Properly detect circular references to the bytecode of other contracts across all function calls.
* Commandline Interface: Model checker option ``--model-checker-targets`` also accepts ``outOfBounds``.
* Low-Level Inliner: Inline ordinary jumps to small blocks and jumps to small blocks that terminate.
* SMTChecker: Report local variables in CHC counterexamples.

View File

@ -389,7 +389,6 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
if (result.empty())
m_errorReporter.fatalTypeError(5005_error, _contract.location(), "Linearization of inheritance graph impossible");
_contract.annotation().linearizedBaseContracts = result;
_contract.annotation().contractDependencies.insert(result.begin() + 1, result.end());
}
template <class T>

View File

@ -2662,24 +2662,6 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
if (contract->abstract())
m_errorReporter.typeError(4614_error, _newExpression.location(), "Cannot instantiate an abstract contract.");
if (m_currentContract)
{
// TODO this is not properly detecting creation-cycles if they go through
// internal library functions or free functions. It will be caught at
// code generation time, but it would of course be better to catch it here.
m_currentContract->annotation().contractDependencies.insert(contract);
solAssert(
!contract->annotation().linearizedBaseContracts.empty(),
"Linearized base contracts not yet available."
);
if (contractDependenciesAreCyclic(*m_currentContract))
m_errorReporter.typeError(
4579_error,
_newExpression.location(),
"Circular reference for contract creation (cannot create instance of derived or same contract)."
);
}
_newExpression.annotation().type = FunctionType::newExpressionType(*contract);
_newExpression.annotation().isPure = false;
}
@ -2953,21 +2935,6 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
_memberAccess.location(),
"\"runtimeCode\" is not available for contracts containing immutable variables."
);
if (m_currentContract)
{
// TODO in the same way as with ``new``,
// this is not properly detecting creation-cycles if they go through
// internal library functions or free functions. It will be caught at
// code generation time, but it would of course be better to catch it here.
m_currentContract->annotation().contractDependencies.insert(&accessedContractType.contractDefinition());
if (contractDependenciesAreCyclic(*m_currentContract))
m_errorReporter.typeError(
4224_error,
_memberAccess.location(),
"Circular reference for contract code access."
);
}
}
else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "name")
annotation.isPure = true;
@ -3455,22 +3422,6 @@ void TypeChecker::checkErrorAndEventParameters(CallableDeclaration const& _calla
}
}
bool TypeChecker::contractDependenciesAreCyclic(
ContractDefinition const& _contract,
std::set<ContractDefinition const*> const& _seenContracts
) const
{
// Naive depth-first search that remembers nodes already seen.
if (_seenContracts.count(&_contract))
return true;
set<ContractDefinition const*> seen(_seenContracts);
seen.insert(&_contract);
for (auto const* c: _contract.annotation().contractDependencies)
if (contractDependenciesAreCyclic(*c, seen))
return true;
return false;
}
Declaration const& TypeChecker::dereference(Identifier const& _identifier) const
{
solAssert(!!_identifier.annotation().referencedDeclaration, "Declaration not stored.");

View File

@ -157,11 +157,6 @@ private:
void checkErrorAndEventParameters(CallableDeclaration const& _callable);
bool contractDependenciesAreCyclic(
ContractDefinition const& _contract,
std::set<ContractDefinition const*> const& _seenContracts = std::set<ContractDefinition const*>()
) const;
/// @returns the referenced declaration and throws on error.
Declaration const& dereference(Identifier const& _identifier) const;
/// @returns the referenced declaration and throws on error.

View File

@ -65,24 +65,7 @@ class ASTConstVisitor;
class ASTNode: private boost::noncopyable
{
public:
struct CompareByID
{
using is_transparent = void;
bool operator()(ASTNode const* _lhs, ASTNode const* _rhs) const
{
return _lhs->id() < _rhs->id();
}
bool operator()(ASTNode const* _lhs, int64_t _rhs) const
{
return _lhs->id() < _rhs;
}
bool operator()(int64_t _lhs, ASTNode const* _rhs) const
{
return _lhs < _rhs->id();
}
};
using CompareByID = frontend::ASTCompareByID<ASTNode>;
using SourceLocation = langutil::SourceLocation;
explicit ASTNode(int64_t _id, SourceLocation _location);

View File

@ -158,9 +158,6 @@ struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocu
/// List of all (direct and indirect) base contracts in order from derived to
/// base, including the contract itself.
std::vector<ContractDefinition const*> linearizedBaseContracts;
/// List of contracts this contract creates, i.e. which need to be compiled first.
/// Also includes all contracts from @a linearizedBaseContracts.
std::set<ContractDefinition const*> contractDependencies;
/// Mapping containing the nodes that define the arguments for base constructors.
/// These can either be inheritance specifiers or modifier invocations.
std::map<FunctionDefinition const*, ASTNode const*> baseConstructorArguments;
@ -168,6 +165,10 @@ struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocu
SetOnce<std::shared_ptr<CallGraph const>> creationCallGraph;
/// A graph with edges representing calls between functions that may happen in a deployed contract.
SetOnce<std::shared_ptr<CallGraph const>> deployedCallGraph;
/// List of contracts whose bytecode is referenced by this contract, e.g. through "new".
/// The Value represents the ast node that referenced the contract.
std::map<ContractDefinition const*, ASTNode const*, ASTCompareByID<ContractDefinition>> contractDependencies;
};
struct CallableDeclarationAnnotation: DeclarationAnnotation

View File

@ -100,6 +100,25 @@ class StructuredDocumentation;
class VariableScope;
template <class T>
struct ASTCompareByID
{
using is_transparent = void;
bool operator()(T const* _lhs, T const* _rhs) const
{
return _lhs->id() < _rhs->id();
}
bool operator()(T const* _lhs, int64_t _rhs) const
{
return _lhs->id() < _rhs;
}
bool operator()(int64_t _lhs, T const* _rhs) const
{
return _lhs < _rhs->id();
}
};
// Used as pointers to AST nodes, to be replaced by more clever pointers, e.g. pointers which do
// not do reference counting but point to a special memory area that is completely released
// explicitly.

View File

@ -41,7 +41,9 @@
#include <algorithm>
#include <limits>
#include <type_traits>
#include <range/v3/view/map.hpp>
using namespace ranges;
using namespace std;
using namespace solidity::langutil;
@ -269,7 +271,7 @@ bool ASTJsonConverter::visit(ContractDefinition const& _node)
make_pair("contractKind", contractKind(_node.contractKind())),
make_pair("abstract", _node.abstract()),
make_pair("baseContracts", toJson(_node.baseContracts())),
make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies, true)),
make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies | views::keys)),
make_pair("nodes", toJson(_node.subNodes())),
make_pair("scope", idOrNull(_node.scope()))
};

View File

@ -63,7 +63,7 @@ struct CallGraph
/// Contracts that need to be compiled before this one can be compiled.
/// The value is the ast node that created the dependency.
std::map<ContractDefinition const*, ASTNode const*, ASTNode::CompareByID> bytecodeDependency;
std::map<ContractDefinition const*, ASTNode const*, ASTCompareByID<ContractDefinition>> bytecodeDependency;
/// Events that may get emitted by functions present in the graph.
std::set<EventDefinition const*, ASTNode::CompareByID> emittedEvents;

View File

@ -71,11 +71,15 @@
#include <libsolutil/SwarmHash.h>
#include <libsolutil/IpfsHash.h>
#include <libsolutil/JSON.h>
#include <libsolutil/Algorithms.h>
#include <json/json.h>
#include <boost/algorithm/string/replace.hpp>
#include <utility>
#include <map>
#include <range/v3/view/concat.hpp>
#include <boost/algorithm/string/replace.hpp>
using namespace std;
using namespace solidity;
@ -104,6 +108,94 @@ CompilerStack::~CompilerStack()
TypeProvider::reset();
}
void CompilerStack::createAndAssignCallGraphs()
{
for (Source const* source: m_sourceOrder)
{
if (!source->ast)
continue;
for (ContractDefinition const* contract: ASTNode::filteredNodes<ContractDefinition>(source->ast->nodes()))
{
ContractDefinitionAnnotation& annotation =
m_contracts.at(contract->fullyQualifiedName()).contract->annotation();
annotation.creationCallGraph = make_unique<CallGraph>(
FunctionCallGraphBuilder::buildCreationGraph(*contract)
);
annotation.deployedCallGraph = make_unique<CallGraph>(
FunctionCallGraphBuilder::buildDeployedGraph(
*contract,
**annotation.creationCallGraph
)
);
solAssert(annotation.contractDependencies.empty(), "contractDependencies expected to be empty?!");
annotation.contractDependencies = annotation.creationCallGraph->get()->bytecodeDependency;
for (auto const& [dependencyContract, referencee]: annotation.deployedCallGraph->get()->bytecodeDependency)
annotation.contractDependencies.emplace(dependencyContract, referencee);
}
}
}
void CompilerStack::findAndReportCyclicContractDependencies()
{
// Cycles we found, used to avoid duplicate reports for the same reference
set<ASTNode const*, ASTNode::CompareByID> foundCycles;
for (Source const* source: m_sourceOrder)
{
if (!source->ast)
continue;
for (ContractDefinition const* contractDefinition: ASTNode::filteredNodes<ContractDefinition>(source->ast->nodes()))
{
util::CycleDetector<ContractDefinition> cycleDetector{[&](
ContractDefinition const& _contract,
util::CycleDetector<ContractDefinition>& _cycleDetector,
size_t _depth
)
{
// No specific reason for exactly that number, just a limit we're unlikely to hit.
if (_depth >= 256)
m_errorReporter.fatalTypeError(
7864_error,
_contract.location(),
"Contract dependencies exhausting cyclic dependency validator"
);
for (auto& [dependencyContract, referencee]: _contract.annotation().contractDependencies)
if (_cycleDetector.run(*dependencyContract))
return;
}};
ContractDefinition const* cycle = cycleDetector.run(*contractDefinition);
if (!cycle)
continue;
ASTNode const* referencee = contractDefinition->annotation().contractDependencies.at(cycle);
if (foundCycles.find(referencee) != foundCycles.end())
continue;
SecondarySourceLocation secondaryLocation{};
secondaryLocation.append("Referenced contract is here:"s, cycle->location());
m_errorReporter.typeError(
7813_error,
referencee->location(),
secondaryLocation,
"Circular reference to contract bytecode either via \"new\" or \"type(...).creationCode\" / \"type(...).runtimeCode\"."
);
foundCycles.emplace(referencee);
}
}
}
std::optional<CompilerStack::Remapping> CompilerStack::parseRemapping(string const& _remapping)
{
auto eq = find(_remapping.begin(), _remapping.end(), '=');
@ -400,27 +492,11 @@ bool CompilerStack::analyze()
if (source->ast && !typeChecker.checkTypeRequirements(*source->ast))
noErrors = false;
// Create & assign callgraphs and check for contract dependency cycles
if (noErrors)
{
for (Source const* source: m_sourceOrder)
if (source->ast)
for (ASTPointer<ASTNode> const& node: source->ast->nodes())
if (auto const* contractDefinition = dynamic_cast<ContractDefinition*>(node.get()))
{
Contract& contractState = m_contracts.at(contractDefinition->fullyQualifiedName());
contractState.contract->annotation().creationCallGraph = make_unique<CallGraph>(
FunctionCallGraphBuilder::buildCreationGraph(
*contractDefinition
)
);
contractState.contract->annotation().deployedCallGraph = make_unique<CallGraph>(
FunctionCallGraphBuilder::buildDeployedGraph(
*contractDefinition,
**contractState.contract->annotation().creationCallGraph
)
);
}
createAndAssignCallGraphs();
findAndReportCyclicContractDependencies();
}
if (noErrors)
@ -1206,7 +1282,7 @@ void CompilerStack::compileContract(
if (_otherCompilers.count(&_contract))
return;
for (auto const* dependency: _contract.annotation().contractDependencies)
for (auto const& [dependency, referencee]: _contract.annotation().contractDependencies)
compileContract(*dependency, _otherCompilers);
if (!_contract.canBeDeployed())
@ -1292,7 +1368,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
);
string dependenciesSource;
for (auto const* dependency: _contract.annotation().contractDependencies)
for (auto const& [dependency, referencee]: _contract.annotation().contractDependencies)
generateIR(*dependency);
if (!_contract.canBeDeployed())

View File

@ -390,6 +390,9 @@ private:
mutable std::optional<std::string const> runtimeSourceMapping;
};
void createAndAssignCallGraphs();
void findAndReportCyclicContractDependencies();
/// Loads the missing sources from @a _ast (named @a _path) using the callback
/// @a m_readFile and stores the absolute paths of all imports in the AST annotations.
/// @returns the newly loaded sources.
@ -495,6 +498,7 @@ private:
std::shared_ptr<GlobalContext> m_globalContext;
std::vector<Source const*> m_sourceOrder;
std::map<std::string const, Contract> m_contracts;
langutil::ErrorList m_errorList;
langutil::ErrorReporter m_errorReporter;
bool m_metadataLiteralSources = false;

View File

@ -120,10 +120,7 @@
"src": "50:1:1"
}
],
"contractDependencies":
[
7
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 17,

View File

@ -63,10 +63,7 @@
"src": "29:1:1"
}
],
"contractDependencies":
[
1
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 4,
@ -100,11 +97,7 @@
"src": "49:1:1"
}
],
"contractDependencies":
[
1,
4
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 7,
@ -139,12 +132,7 @@
"src": "69:1:1"
}
],
"contractDependencies":
[
1,
4,
7
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 10,
@ -180,13 +168,7 @@
"src": "89:1:1"
}
],
"contractDependencies":
[
1,
4,
7,
10
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 13,

View File

@ -51,10 +51,7 @@
"src": "30:2:1"
}
],
"contractDependencies":
[
1
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 4,

View File

@ -12,10 +12,10 @@
],
"C":
[
31
29
]
},
"id": 32,
"id": 30,
"nodeType": "SourceUnit",
"nodes":
[
@ -40,7 +40,7 @@
{
"id": 3,
"nodeType": "Block",
"src": "36:2:1",
"src": "44:2:1",
"statements": []
},
"functionSelector": "a399b6a2",
@ -63,20 +63,20 @@
"id": 2,
"nodeType": "ParameterList",
"parameters": [],
"src": "36:0:1"
"src": "44:0:1"
},
"scope": 5,
"src": "14:24:1",
"src": "14:32:1",
"stateMutability": "nonpayable",
"virtual": false,
"virtual": true,
"visibility": "public"
}
],
"scope": 32,
"src": "0:40:1"
"scope": 30,
"src": "0:48:1"
},
{
"abstract": false,
"abstract": true,
"baseContracts":
[
{
@ -86,17 +86,14 @@
"name": "A",
"nodeType": "IdentifierPath",
"referencedDeclaration": 5,
"src": "55:1:1"
"src": "72:1:1"
},
"id": 7,
"nodeType": "InheritanceSpecifier",
"src": "55:1:1"
"src": "72:1:1"
}
],
"contractDependencies":
[
5
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": false,
"id": 16,
@ -106,7 +103,7 @@
5
],
"name": "B",
"nameLocation": "50:1:1",
"nameLocation": "67:1:1",
"nodeType": "ContractDefinition",
"nodes":
[
@ -117,26 +114,26 @@
"kind": "function",
"modifiers": [],
"name": "foo",
"nameLocation": "69:3:1",
"nameLocation": "86:3:1",
"nodeType": "FunctionDefinition",
"parameters":
{
"id": 8,
"nodeType": "ParameterList",
"parameters": [],
"src": "72:2:1"
"src": "89:2:1"
},
"returnParameters":
{
"id": 9,
"nodeType": "ParameterList",
"parameters": [],
"src": "81:0:1"
"src": "106:0:1"
},
"scope": 16,
"src": "60:22:1",
"src": "77:30:1",
"stateMutability": "nonpayable",
"virtual": false,
"virtual": true,
"visibility": "public"
},
{
@ -148,7 +145,7 @@
{
"id": 14,
"nodeType": "Block",
"src": "115:2:1",
"src": "148:2:1",
"statements": []
},
"functionSelector": "a399b6a2",
@ -157,38 +154,38 @@
"kind": "function",
"modifiers": [],
"name": "faa",
"nameLocation": "93:3:1",
"nameLocation": "118:3:1",
"nodeType": "FunctionDefinition",
"overrides":
{
"id": 12,
"nodeType": "OverrideSpecifier",
"overrides": [],
"src": "106:8:1"
"src": "139:8:1"
},
"parameters":
{
"id": 11,
"nodeType": "ParameterList",
"parameters": [],
"src": "96:2:1"
"src": "121:2:1"
},
"returnParameters":
{
"id": 13,
"nodeType": "ParameterList",
"parameters": [],
"src": "115:0:1"
"src": "148:0:1"
},
"scope": 16,
"src": "84:33:1",
"src": "109:41:1",
"stateMutability": "nonpayable",
"virtual": false,
"virtual": true,
"visibility": "public"
}
],
"scope": 32,
"src": "41:78:1"
"scope": 30,
"src": "49:103:1"
},
{
"abstract": false,
@ -201,29 +198,25 @@
"name": "B",
"nodeType": "IdentifierPath",
"referencedDeclaration": 16,
"src": "134:1:1"
"src": "167:1:1"
},
"id": 18,
"nodeType": "InheritanceSpecifier",
"src": "134:1:1"
"src": "167:1:1"
}
],
"contractDependencies":
[
5,
16
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 31,
"id": 29,
"linearizedBaseContracts":
[
31,
29,
16,
5
],
"name": "C",
"nameLocation": "129:1:1",
"nameLocation": "162:1:1",
"nodeType": "ContractDefinition",
"nodes":
[
@ -236,7 +229,7 @@
{
"id": 22,
"nodeType": "Block",
"src": "170:3:1",
"src": "203:3:1",
"statements": []
},
"functionSelector": "c2985578",
@ -245,31 +238,31 @@
"kind": "function",
"modifiers": [],
"name": "foo",
"nameLocation": "148:3:1",
"nameLocation": "181:3:1",
"nodeType": "FunctionDefinition",
"overrides":
{
"id": 20,
"nodeType": "OverrideSpecifier",
"overrides": [],
"src": "161:8:1"
"src": "194:8:1"
},
"parameters":
{
"id": 19,
"nodeType": "ParameterList",
"parameters": [],
"src": "151:2:1"
"src": "184:2:1"
},
"returnParameters":
{
"id": 21,
"nodeType": "ParameterList",
"parameters": [],
"src": "170:0:1"
"src": "203:0:1"
},
"scope": 31,
"src": "139:34:1",
"scope": 29,
"src": "172:34:1",
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
@ -281,66 +274,50 @@
],
"body":
{
"id": 29,
"id": 27,
"nodeType": "Block",
"src": "212:2:1",
"src": "239:3:1",
"statements": []
},
"functionSelector": "a399b6a2",
"id": 30,
"id": 28,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "faa",
"nameLocation": "184:3:1",
"nameLocation": "217:3:1",
"nodeType": "FunctionDefinition",
"overrides":
{
"id": 27,
"id": 25,
"nodeType": "OverrideSpecifier",
"overrides":
[
{
"id": 25,
"name": "A",
"nodeType": "IdentifierPath",
"referencedDeclaration": 5,
"src": "206:1:1"
},
{
"id": 26,
"name": "B",
"nodeType": "IdentifierPath",
"referencedDeclaration": 16,
"src": "209:1:1"
}
],
"src": "197:14:1"
"overrides": [],
"src": "230:8:1"
},
"parameters":
{
"id": 24,
"nodeType": "ParameterList",
"parameters": [],
"src": "187:2:1"
"src": "220:2:1"
},
"returnParameters":
{
"id": 28,
"id": 26,
"nodeType": "ParameterList",
"parameters": [],
"src": "212:0:1"
"src": "239:0:1"
},
"scope": 31,
"src": "175:39:1",
"scope": 29,
"src": "208:34:1",
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"scope": 32,
"src": "120:96:1"
"scope": 30,
"src": "153:91:1"
}
],
"src": "0:217:1"
"src": "0:245:1"
}

View File

@ -1,13 +1,13 @@
contract A {
function faa() public {}
function faa() public virtual {}
}
contract B is A {
function foo() public;
function faa() public override {}
abstract contract B is A {
function foo() public virtual;
function faa() public virtual override {}
}
contract C is B {
function foo() public override { }
function faa() public override(A, B) {}
function faa() public override { }
}
// ----

View File

@ -1,6 +1,6 @@
{
"absolutePath": "a",
"id": 32,
"id": 30,
"nodeType": "SourceUnit",
"nodes":
[
@ -20,7 +20,7 @@
{
"id": 3,
"nodeType": "Block",
"src": "36:2:1",
"src": "44:2:1",
"statements": []
},
"id": 4,
@ -42,18 +42,18 @@
"id": 2,
"nodeType": "ParameterList",
"parameters": [],
"src": "36:0:1"
"src": "44:0:1"
},
"src": "14:24:1",
"src": "14:32:1",
"stateMutability": "nonpayable",
"virtual": false,
"virtual": true,
"visibility": "public"
}
],
"src": "0:40:1"
"src": "0:48:1"
},
{
"abstract": false,
"abstract": true,
"baseContracts":
[
{
@ -62,18 +62,18 @@
"id": 6,
"name": "A",
"nodeType": "IdentifierPath",
"src": "55:1:1"
"src": "72:1:1"
},
"id": 7,
"nodeType": "InheritanceSpecifier",
"src": "55:1:1"
"src": "72:1:1"
}
],
"contractDependencies": [],
"contractKind": "contract",
"id": 16,
"name": "B",
"nameLocation": "50:1:1",
"nameLocation": "67:1:1",
"nodeType": "ContractDefinition",
"nodes":
[
@ -83,25 +83,25 @@
"kind": "function",
"modifiers": [],
"name": "foo",
"nameLocation": "69:3:1",
"nameLocation": "86:3:1",
"nodeType": "FunctionDefinition",
"parameters":
{
"id": 8,
"nodeType": "ParameterList",
"parameters": [],
"src": "72:2:1"
"src": "89:2:1"
},
"returnParameters":
{
"id": 9,
"nodeType": "ParameterList",
"parameters": [],
"src": "81:0:1"
"src": "106:0:1"
},
"src": "60:22:1",
"src": "77:30:1",
"stateMutability": "nonpayable",
"virtual": false,
"virtual": true,
"visibility": "public"
},
{
@ -109,7 +109,7 @@
{
"id": 14,
"nodeType": "Block",
"src": "115:2:1",
"src": "148:2:1",
"statements": []
},
"id": 15,
@ -117,36 +117,36 @@
"kind": "function",
"modifiers": [],
"name": "faa",
"nameLocation": "93:3:1",
"nameLocation": "118:3:1",
"nodeType": "FunctionDefinition",
"overrides":
{
"id": 12,
"nodeType": "OverrideSpecifier",
"overrides": [],
"src": "106:8:1"
"src": "139:8:1"
},
"parameters":
{
"id": 11,
"nodeType": "ParameterList",
"parameters": [],
"src": "96:2:1"
"src": "121:2:1"
},
"returnParameters":
{
"id": 13,
"nodeType": "ParameterList",
"parameters": [],
"src": "115:0:1"
"src": "148:0:1"
},
"src": "84:33:1",
"src": "109:41:1",
"stateMutability": "nonpayable",
"virtual": false,
"virtual": true,
"visibility": "public"
}
],
"src": "41:78:1"
"src": "49:103:1"
},
{
"abstract": false,
@ -158,18 +158,18 @@
"id": 17,
"name": "B",
"nodeType": "IdentifierPath",
"src": "134:1:1"
"src": "167:1:1"
},
"id": 18,
"nodeType": "InheritanceSpecifier",
"src": "134:1:1"
"src": "167:1:1"
}
],
"contractDependencies": [],
"contractKind": "contract",
"id": 31,
"id": 29,
"name": "C",
"nameLocation": "129:1:1",
"nameLocation": "162:1:1",
"nodeType": "ContractDefinition",
"nodes":
[
@ -178,7 +178,7 @@
{
"id": 22,
"nodeType": "Block",
"src": "170:3:1",
"src": "203:3:1",
"statements": []
},
"id": 23,
@ -186,30 +186,30 @@
"kind": "function",
"modifiers": [],
"name": "foo",
"nameLocation": "148:3:1",
"nameLocation": "181:3:1",
"nodeType": "FunctionDefinition",
"overrides":
{
"id": 20,
"nodeType": "OverrideSpecifier",
"overrides": [],
"src": "161:8:1"
"src": "194:8:1"
},
"parameters":
{
"id": 19,
"nodeType": "ParameterList",
"parameters": [],
"src": "151:2:1"
"src": "184:2:1"
},
"returnParameters":
{
"id": 21,
"nodeType": "ParameterList",
"parameters": [],
"src": "170:0:1"
"src": "203:0:1"
},
"src": "139:34:1",
"src": "172:34:1",
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
@ -217,61 +217,47 @@
{
"body":
{
"id": 29,
"id": 27,
"nodeType": "Block",
"src": "212:2:1",
"src": "239:3:1",
"statements": []
},
"id": 30,
"id": 28,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "faa",
"nameLocation": "184:3:1",
"nameLocation": "217:3:1",
"nodeType": "FunctionDefinition",
"overrides":
{
"id": 27,
"id": 25,
"nodeType": "OverrideSpecifier",
"overrides":
[
{
"id": 25,
"name": "A",
"nodeType": "IdentifierPath",
"src": "206:1:1"
},
{
"id": 26,
"name": "B",
"nodeType": "IdentifierPath",
"src": "209:1:1"
}
],
"src": "197:14:1"
"overrides": [],
"src": "230:8:1"
},
"parameters":
{
"id": 24,
"nodeType": "ParameterList",
"parameters": [],
"src": "187:2:1"
"src": "220:2:1"
},
"returnParameters":
{
"id": 28,
"id": 26,
"nodeType": "ParameterList",
"parameters": [],
"src": "212:0:1"
"src": "239:0:1"
},
"src": "175:39:1",
"src": "208:34:1",
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"src": "120:96:1"
"src": "153:91:1"
}
],
"src": "0:217:1"
"src": "0:245:1"
}

View File

@ -162,11 +162,7 @@
"src": "117:1:1"
}
],
"contractDependencies":
[
5,
10
],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 22,

View File

@ -0,0 +1,7 @@
contract D {}
contract C is D {}
contract E is D
{
function foo() public { new C(); }
}
// ----

View File

@ -0,0 +1,6 @@
contract A { function foo() public { new D(); } }
contract C { function foo() public { new A(); } }
contract D is C {}
// ----
// TypeError 7813: (37-42): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (87-92): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -0,0 +1,11 @@
function f()
{
new D();
}
contract D
{
receive() external payable { f; }
}
// ----
// TypeError 7813: (16-21): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -0,0 +1,3 @@
contract C { function foo(D _d) public { _d.foo(this); } }
contract D { function foo(C _c) public { _c.foo(this); } }
// ----

View File

@ -0,0 +1,11 @@
contract C
{
// Internal uncalled function should not cause an cyclic dep. error
function foo() internal { new D(); }
function callFoo() virtual public { foo(); }
}
contract D is C
{
function callFoo() override public {}
}

View File

@ -0,0 +1,3 @@
contract C { function foo() internal { new D(); } }
contract D { function foo() internal { new C(); } }
// ----

View File

@ -0,0 +1,3 @@
library L1 { function foo() internal { L2.foo(); } }
library L2 { function foo() internal { L1.foo(); } }
// ----

View File

@ -0,0 +1,9 @@
contract C {
function foo() public pure { D; }
}
contract D {
function foo() public pure { C; }
}
// ----
// Warning 6133: (43-44): Statement has no effect.
// Warning 6133: (93-94): Statement has no effect.

View File

@ -0,0 +1,5 @@
contract C {
constructor() { new C(); }
}
// ----
// TypeError 7813: (30-35): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -0,0 +1,13 @@
contract A { B x = new B(); }
contract B { C x = new C(); }
contract C { D x = new D(); }
contract D { E x = new E(); }
contract E { F x = new F(); }
contract F { E x = new E(); }
// ----
// TypeError 7813: (19-24): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (49-54): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (79-84): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (109-114): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (139-144): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (169-174): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -0,0 +1,9 @@
contract C {
function foo() public pure { type(D); }
}
contract D {
function foo() public pure { type(C); }
}
// ----
// Warning 6133: (43-50): Statement has no effect.
// Warning 6133: (99-106): Statement has no effect.

View File

@ -0,0 +1,773 @@
contract D {
function f() public {
new C();
}
}
contract C {
constructor() { new C2(); }
}
contract C2 {
constructor() { new C3(); }
}
contract C3 {
constructor() { new C4(); }
}
contract C4 {
constructor() { new C5(); }
}
contract C5 {
constructor() { new C6(); }
}
contract C6 {
constructor() { new C7(); }
}
contract C7 {
constructor() { new C8(); }
}
contract C8 {
constructor() { new C9(); }
}
contract C9 {
constructor() { new C10(); }
}
contract C10 {
constructor() { new C11(); }
}
contract C11 {
constructor() { new C12(); }
}
contract C12 {
constructor() { new C13(); }
}
contract C13 {
constructor() { new C14(); }
}
contract C14 {
constructor() { new C15(); }
}
contract C15 {
constructor() { new C16(); }
}
contract C16 {
constructor() { new C17(); }
}
contract C17 {
constructor() { new C18(); }
}
contract C18 {
constructor() { new C19(); }
}
contract C19 {
constructor() { new C20(); }
}
contract C20 {
constructor() { new C21(); }
}
contract C21 {
constructor() { new C22(); }
}
contract C22 {
constructor() { new C23(); }
}
contract C23 {
constructor() { new C24(); }
}
contract C24 {
constructor() { new C25(); }
}
contract C25 {
constructor() { new C26(); }
}
contract C26 {
constructor() { new C27(); }
}
contract C27 {
constructor() { new C28(); }
}
contract C28 {
constructor() { new C29(); }
}
contract C29 {
constructor() { new C30(); }
}
contract C30 {
constructor() { new C31(); }
}
contract C31 {
constructor() { new C32(); }
}
contract C32 {
constructor() { new C33(); }
}
contract C33 {
constructor() { new C34(); }
}
contract C34 {
constructor() { new C35(); }
}
contract C35 {
constructor() { new C36(); }
}
contract C36 {
constructor() { new C37(); }
}
contract C37 {
constructor() { new C38(); }
}
contract C38 {
constructor() { new C39(); }
}
contract C39 {
constructor() { new C40(); }
}
contract C40 {
constructor() { new C41(); }
}
contract C41 {
constructor() { new C42(); }
}
contract C42 {
constructor() { new C43(); }
}
contract C43 {
constructor() { new C44(); }
}
contract C44 {
constructor() { new C45(); }
}
contract C45 {
constructor() { new C46(); }
}
contract C46 {
constructor() { new C47(); }
}
contract C47 {
constructor() { new C48(); }
}
contract C48 {
constructor() { new C49(); }
}
contract C49 {
constructor() { new C50(); }
}
contract C50 {
constructor() { new C51(); }
}
contract C51 {
constructor() { new C52(); }
}
contract C52 {
constructor() { new C53(); }
}
contract C53 {
constructor() { new C54(); }
}
contract C54 {
constructor() { new C55(); }
}
contract C55 {
constructor() { new C56(); }
}
contract C56 {
constructor() { new C57(); }
}
contract C57 {
constructor() { new C58(); }
}
contract C58 {
constructor() { new C59(); }
}
contract C59 {
constructor() { new C60(); }
}
contract C60 {
constructor() { new C61(); }
}
contract C61 {
constructor() { new C62(); }
}
contract C62 {
constructor() { new C63(); }
}
contract C63 {
constructor() { new C64(); }
}
contract C64 {
constructor() { new C65(); }
}
contract C65 {
constructor() { new C66(); }
}
contract C66 {
constructor() { new C67(); }
}
contract C67 {
constructor() { new C68(); }
}
contract C68 {
constructor() { new C69(); }
}
contract C69 {
constructor() { new C70(); }
}
contract C70 {
constructor() { new C71(); }
}
contract C71 {
constructor() { new C72(); }
}
contract C72 {
constructor() { new C73(); }
}
contract C73 {
constructor() { new C74(); }
}
contract C74 {
constructor() { new C75(); }
}
contract C75 {
constructor() { new C76(); }
}
contract C76 {
constructor() { new C77(); }
}
contract C77 {
constructor() { new C78(); }
}
contract C78 {
constructor() { new C79(); }
}
contract C79 {
constructor() { new C80(); }
}
contract C80 {
constructor() { new C81(); }
}
contract C81 {
constructor() { new C82(); }
}
contract C82 {
constructor() { new C83(); }
}
contract C83 {
constructor() { new C84(); }
}
contract C84 {
constructor() { new C85(); }
}
contract C85 {
constructor() { new C86(); }
}
contract C86 {
constructor() { new C87(); }
}
contract C87 {
constructor() { new C88(); }
}
contract C88 {
constructor() { new C89(); }
}
contract C89 {
constructor() { new C90(); }
}
contract C90 {
constructor() { new C91(); }
}
contract C91 {
constructor() { new C92(); }
}
contract C92 {
constructor() { new C93(); }
}
contract C93 {
constructor() { new C94(); }
}
contract C94 {
constructor() { new C95(); }
}
contract C95 {
constructor() { new C96(); }
}
contract C96 {
constructor() { new C97(); }
}
contract C97 {
constructor() { new C98(); }
}
contract C98 {
constructor() { new C99(); }
}
contract C99 {
constructor() { new C100(); }
}
contract C100 {
constructor() { new C101(); }
}
contract C101 {
constructor() { new C102(); }
}
contract C102 {
constructor() { new C103(); }
}
contract C103 {
constructor() { new C104(); }
}
contract C104 {
constructor() { new C105(); }
}
contract C105 {
constructor() { new C106(); }
}
contract C106 {
constructor() { new C107(); }
}
contract C107 {
constructor() { new C108(); }
}
contract C108 {
constructor() { new C109(); }
}
contract C109 {
constructor() { new C110(); }
}
contract C110 {
constructor() { new C111(); }
}
contract C111 {
constructor() { new C112(); }
}
contract C112 {
constructor() { new C113(); }
}
contract C113 {
constructor() { new C114(); }
}
contract C114 {
constructor() { new C115(); }
}
contract C115 {
constructor() { new C116(); }
}
contract C116 {
constructor() { new C117(); }
}
contract C117 {
constructor() { new C118(); }
}
contract C118 {
constructor() { new C119(); }
}
contract C119 {
constructor() { new C120(); }
}
contract C120 {
constructor() { new C121(); }
}
contract C121 {
constructor() { new C122(); }
}
contract C122 {
constructor() { new C123(); }
}
contract C123 {
constructor() { new C124(); }
}
contract C124 {
constructor() { new C125(); }
}
contract C125 {
constructor() { new C126(); }
}
contract C126 {
constructor() { new C127(); }
}
contract C127 {
constructor() { new C128(); }
}
contract C128 {
constructor() { new C129(); }
}
contract C129 {
constructor() { new C130(); }
}
contract C130 {
constructor() { new C131(); }
}
contract C131 {
constructor() { new C132(); }
}
contract C132 {
constructor() { new C133(); }
}
contract C133 {
constructor() { new C134(); }
}
contract C134 {
constructor() { new C135(); }
}
contract C135 {
constructor() { new C136(); }
}
contract C136 {
constructor() { new C137(); }
}
contract C137 {
constructor() { new C138(); }
}
contract C138 {
constructor() { new C139(); }
}
contract C139 {
constructor() { new C140(); }
}
contract C140 {
constructor() { new C141(); }
}
contract C141 {
constructor() { new C142(); }
}
contract C142 {
constructor() { new C143(); }
}
contract C143 {
constructor() { new C144(); }
}
contract C144 {
constructor() { new C145(); }
}
contract C145 {
constructor() { new C146(); }
}
contract C146 {
constructor() { new C147(); }
}
contract C147 {
constructor() { new C148(); }
}
contract C148 {
constructor() { new C149(); }
}
contract C149 {
constructor() { new C150(); }
}
contract C150 {
constructor() { new C151(); }
}
contract C151 {
constructor() { new C152(); }
}
contract C152 {
constructor() { new C153(); }
}
contract C153 {
constructor() { new C154(); }
}
contract C154 {
constructor() { new C155(); }
}
contract C155 {
constructor() { new C156(); }
}
contract C156 {
constructor() { new C157(); }
}
contract C157 {
constructor() { new C158(); }
}
contract C158 {
constructor() { new C159(); }
}
contract C159 {
constructor() { new C160(); }
}
contract C160 {
constructor() { new C161(); }
}
contract C161 {
constructor() { new C162(); }
}
contract C162 {
constructor() { new C163(); }
}
contract C163 {
constructor() { new C164(); }
}
contract C164 {
constructor() { new C165(); }
}
contract C165 {
constructor() { new C166(); }
}
contract C166 {
constructor() { new C167(); }
}
contract C167 {
constructor() { new C168(); }
}
contract C168 {
constructor() { new C169(); }
}
contract C169 {
constructor() { new C170(); }
}
contract C170 {
constructor() { new C171(); }
}
contract C171 {
constructor() { new C172(); }
}
contract C172 {
constructor() { new C173(); }
}
contract C173 {
constructor() { new C174(); }
}
contract C174 {
constructor() { new C175(); }
}
contract C175 {
constructor() { new C176(); }
}
contract C176 {
constructor() { new C177(); }
}
contract C177 {
constructor() { new C178(); }
}
contract C178 {
constructor() { new C179(); }
}
contract C179 {
constructor() { new C180(); }
}
contract C180 {
constructor() { new C181(); }
}
contract C181 {
constructor() { new C182(); }
}
contract C182 {
constructor() { new C183(); }
}
contract C183 {
constructor() { new C184(); }
}
contract C184 {
constructor() { new C185(); }
}
contract C185 {
constructor() { new C186(); }
}
contract C186 {
constructor() { new C187(); }
}
contract C187 {
constructor() { new C188(); }
}
contract C188 {
constructor() { new C189(); }
}
contract C189 {
constructor() { new C190(); }
}
contract C190 {
constructor() { new C191(); }
}
contract C191 {
constructor() { new C192(); }
}
contract C192 {
constructor() { new C193(); }
}
contract C193 {
constructor() { new C194(); }
}
contract C194 {
constructor() { new C195(); }
}
contract C195 {
constructor() { new C196(); }
}
contract C196 {
constructor() { new C197(); }
}
contract C197 {
constructor() { new C198(); }
}
contract C198 {
constructor() { new C199(); }
}
contract C199 {
constructor() { new C200(); }
}
contract C200 {
constructor() { new C201(); }
}
contract C201 {
constructor() { new C202(); }
}
contract C202 {
constructor() { new C203(); }
}
contract C203 {
constructor() { new C204(); }
}
contract C204 {
constructor() { new C205(); }
}
contract C205 {
constructor() { new C206(); }
}
contract C206 {
constructor() { new C207(); }
}
contract C207 {
constructor() { new C208(); }
}
contract C208 {
constructor() { new C209(); }
}
contract C209 {
constructor() { new C210(); }
}
contract C210 {
constructor() { new C211(); }
}
contract C211 {
constructor() { new C212(); }
}
contract C212 {
constructor() { new C213(); }
}
contract C213 {
constructor() { new C214(); }
}
contract C214 {
constructor() { new C215(); }
}
contract C215 {
constructor() { new C216(); }
}
contract C216 {
constructor() { new C217(); }
}
contract C217 {
constructor() { new C218(); }
}
contract C218 {
constructor() { new C219(); }
}
contract C219 {
constructor() { new C220(); }
}
contract C220 {
constructor() { new C221(); }
}
contract C221 {
constructor() { new C222(); }
}
contract C222 {
constructor() { new C223(); }
}
contract C223 {
constructor() { new C224(); }
}
contract C224 {
constructor() { new C225(); }
}
contract C225 {
constructor() { new C226(); }
}
contract C226 {
constructor() { new C227(); }
}
contract C227 {
constructor() { new C228(); }
}
contract C228 {
constructor() { new C229(); }
}
contract C229 {
constructor() { new C230(); }
}
contract C230 {
constructor() { new C231(); }
}
contract C231 {
constructor() { new C232(); }
}
contract C232 {
constructor() { new C233(); }
}
contract C233 {
constructor() { new C234(); }
}
contract C234 {
constructor() { new C235(); }
}
contract C235 {
constructor() { new C236(); }
}
contract C236 {
constructor() { new C237(); }
}
contract C237 {
constructor() { new C238(); }
}
contract C238 {
constructor() { new C239(); }
}
contract C239 {
constructor() { new C240(); }
}
contract C240 {
constructor() { new C241(); }
}
contract C241 {
constructor() { new C242(); }
}
contract C242 {
constructor() { new C243(); }
}
contract C243 {
constructor() { new C244(); }
}
contract C244 {
constructor() { new C245(); }
}
contract C245 {
constructor() { new C246(); }
}
contract C246 {
constructor() { new C247(); }
}
contract C247 {
constructor() { new C248(); }
}
contract C248 {
constructor() { new C249(); }
}
contract C249 {
constructor() { new C250(); }
}
contract C250 {
constructor() { new C251(); }
}
contract C251 {
constructor() { new C252(); }
}
contract C252 {
constructor() { new C253(); }
}
contract C253 {
constructor() { new C254(); }
}
contract C254 {
constructor() { new C255(); }
}
contract C255 {
constructor() { new C(); }
}
// ----
// TypeError 7864: (13057-13105): Contract dependencies exhausting cyclic dependency validator

View File

@ -0,0 +1,18 @@
library L {
function f() internal {
new C();
}
}
contract D {
function f() public {
L.f();
}
}
contract C {
constructor() { new D(); }
}
// ----
// TypeError 7813: (48-53): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (161-166): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -0,0 +1,18 @@
// Checks that error is triggered no matter which order
function l() {
s();
}
function s() {
new C();
}
contract D {
function f() public {
l();
}
}
contract C {
constructor() { new D(); }
}
// ----
// TypeError 7813: (98-103): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (187-192): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -0,0 +1,18 @@
// Checks that error is triggered no matter which order
contract D {
function f() public {
l();
}
}
contract C {
constructor() { new D(); }
}
function l() {
s();
}
function s() {
new C();
}
// ----
// TypeError 7813: (207-212): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (149-154): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -1,22 +1,26 @@
contract Base {
function f() public pure returns (uint) {}
}
contract Test is Base {
contract Test1 is Base {
function creation() public pure returns (bytes memory) {
return type(Test).creationCode;
return type(Test1).creationCode;
}
}
contract Test2 is Base {
function runtime() public pure returns (bytes memory) {
return type(Test).runtimeCode;
return type(Test2).runtimeCode;
}
}
contract Test3 is Base {
function creationBase() public pure returns (bytes memory) {
return type(Base).creationCode;
}
}
contract Test4 is Base {
function runtimeBase() public pure returns (bytes memory) {
return type(Base).runtimeCode;
}
}
// ----
// TypeError 4224: (165-188): Circular reference for contract code access.
// TypeError 4224: (271-293): Circular reference for contract code access.
// TypeError 4224: (381-404): Circular reference for contract code access.
// TypeError 4224: (491-513): Circular reference for contract code access.
// TypeError 7813: (166-190): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (300-323): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -9,4 +9,5 @@ contract B {
}
}
// ----
// TypeError 4224: (133-152): Circular reference for contract code access.
// TypeError 7813: (52-71): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (133-152): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -2,4 +2,4 @@ contract Test {
function f() public { Test x = new Test(); }
}
// ----
// TypeError 4579: (51-59): Circular reference for contract creation (cannot create instance of derived or same contract).
// TypeError 7813: (51-59): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".

View File

@ -2,4 +2,6 @@ contract A { function f() public { new B(); } }
contract B { function f() public { new C(); } }
contract C { function f() public { new A(); } }
// ----
// TypeError 4579: (131-136): Circular reference for contract creation (cannot create instance of derived or same contract).
// TypeError 7813: (35-40): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (83-88): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".
// TypeError 7813: (131-136): Circular reference to contract bytecode either via "new" or "type(...).creationCode" / "type(...).runtimeCode".