Merge pull request #4631 from ethereum/cp-cycle-detection-recursion-guard

Guard CycleDetector against recursion exhaustion.
This commit is contained in:
Alex Beregszaszi 2018-08-01 12:48:46 +01:00 committed by GitHub
commit 8d05770e59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 806 additions and 6 deletions

View File

@ -46,6 +46,7 @@ Breaking Changes:
* Type Checker: Disallow specifying base constructor arguments multiple times in the same inheritance hierarchy. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Disallow calling constructor with wrong argument count. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Disallow uninitialized storage variables. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Detecting cyclic dependencies in variables and structs is limited in recursion to 256.
* Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``.
* Type Checker: Fallback function must be external. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode.

View File

@ -32,11 +32,13 @@ template <typename V>
class CycleDetector
{
public:
using Visitor = std::function<void(V const&, CycleDetector&, size_t)>;
/// Initializes the cycle detector
/// @param _visit function that is given the current vertex
/// and is supposed to call @a run on all
/// adjacent vertices.
explicit CycleDetector(std::function<void(V const&, CycleDetector&)> _visit):
explicit CycleDetector(Visitor _visit):
m_visit(std::move(_visit))
{ }
@ -55,7 +57,7 @@ public:
m_processing.insert(&_vertex);
m_depth++;
m_visit(_vertex, *this);
m_visit(_vertex, *this, m_depth);
m_depth--;
if (m_firstCycleVertex && m_depth == 1)
m_firstCycleVertex = &_vertex;
@ -66,7 +68,7 @@ public:
}
private:
std::function<void(V const&, CycleDetector&)> m_visit;
Visitor m_visit;
std::set<V const*> m_processing;
std::set<V const*> m_processed;
size_t m_depth = 0;

View File

@ -91,8 +91,11 @@ bool PostTypeChecker::visit(Identifier const& _identifier)
VariableDeclaration const* PostTypeChecker::findCycle(VariableDeclaration const& _startingFrom)
{
auto visitor = [&](VariableDeclaration const& _variable, CycleDetector<VariableDeclaration>& _cycleDetector)
auto visitor = [&](VariableDeclaration const& _variable, CycleDetector<VariableDeclaration>& _cycleDetector, size_t _depth)
{
if (_depth >= 256)
m_errorReporter.fatalDeclarationError(_variable.location(), "Variable definition exhausting cyclic dependency validator.");
// Iterating through the dependencies needs to be deterministic and thus cannot
// depend on the memory layout.
// Because of that, we sort by AST node id.

View File

@ -595,8 +595,11 @@ bool TypeChecker::visit(StructDefinition const& _struct)
m_errorReporter.typeError(member->location(), "Type cannot be used in struct.");
// Check recursion, fatal error if detected.
auto visitor = [&](StructDefinition const& _struct, CycleDetector<StructDefinition>& _cycleDetector)
auto visitor = [&](StructDefinition const& _struct, CycleDetector<StructDefinition>& _cycleDetector, size_t _depth)
{
if (_depth >= 256)
m_errorReporter.fatalDeclarationError(_struct.location(), "Struct definition exhausting cyclic dependency validator.");
for (ASTPointer<VariableDeclaration> const& member: _struct.members())
{
Type const* memberType = type(*member).get();

View File

@ -2119,7 +2119,7 @@ bool StructType::recursive() const
{
if (!m_recursive.is_initialized())
{
auto visitor = [&](StructDefinition const& _struct, CycleDetector<StructDefinition>& _cycleDetector)
auto visitor = [&](StructDefinition const& _struct, CycleDetector<StructDefinition>& _cycleDetector, size_t /*_depth*/)
{
for (ASTPointer<VariableDeclaration> const& variable: _struct.members())
{

View File

@ -0,0 +1,262 @@
contract A {}
contract Main {
A constant B = C;
A constant C = D;
A constant D = E;
A constant E = F;
A constant F = G;
A constant G = H;
A constant H = I;
A constant I = J;
A constant J = K;
A constant K = L;
A constant L = M;
A constant M = N;
A constant N = O;
A constant O = P;
A constant P = Q;
A constant Q = R;
A constant R = S;
A constant S = T;
A constant T = U;
A constant U = V;
A constant V = W;
A constant W = X;
A constant X = Y;
A constant Y = Z;
A constant Z = BA;
A constant BA = BB;
A constant BB = BC;
A constant BC = BD;
A constant BD = BE;
A constant BE = BF;
A constant BF = BG;
A constant BG = BH;
A constant BH = BI;
A constant BI = BJ;
A constant BJ = BK;
A constant BK = BL;
A constant BL = BM;
A constant BM = BN;
A constant BN = BO;
A constant BO = BP;
A constant BP = BQ;
A constant BQ = BR;
A constant BR = BS;
A constant BS = BT;
A constant BT = BU;
A constant BU = BV;
A constant BV = BW;
A constant BW = BX;
A constant BX = BY;
A constant BY = BZ;
A constant BZ = CA;
A constant CA = CB;
A constant CB = CC;
A constant CC = CD;
A constant CD = CE;
A constant CE = CF;
A constant CF = CG;
A constant CG = CH;
A constant CH = CI;
A constant CI = CJ;
A constant CJ = CK;
A constant CK = CL;
A constant CL = CM;
A constant CM = CN;
A constant CN = CO;
A constant CO = CP;
A constant CP = CQ;
A constant CQ = CR;
A constant CR = CS;
A constant CS = CT;
A constant CT = CU;
A constant CU = CV;
A constant CV = CW;
A constant CW = CX;
A constant CX = CY;
A constant CY = CZ;
A constant CZ = DA;
A constant DA = DB;
A constant DB = DC;
A constant DC = DD;
A constant DD = DE;
A constant DE = DF;
A constant DF = DG;
A constant DG = DH;
A constant DH = DI;
A constant DI = DJ;
A constant DJ = DK;
A constant DK = DL;
A constant DL = DM;
A constant DM = DN;
A constant DN = DO;
A constant DO = DP;
A constant DP = DQ;
A constant DQ = DR;
A constant DR = DS;
A constant DS = DT;
A constant DT = DU;
A constant DU = DV;
A constant DV = DW;
A constant DW = DX;
A constant DX = DY;
A constant DY = DZ;
A constant DZ = EA;
A constant EA = EB;
A constant EB = EC;
A constant EC = ED;
A constant ED = EE;
A constant EE = EF;
A constant EF = EG;
A constant EG = EH;
A constant EH = EI;
A constant EI = EJ;
A constant EJ = EK;
A constant EK = EL;
A constant EL = EM;
A constant EM = EN;
A constant EN = EO;
A constant EO = EP;
A constant EP = EQ;
A constant EQ = ER;
A constant ER = ES;
A constant ES = ET;
A constant ET = EU;
A constant EU = EV;
A constant EV = EW;
A constant EW = EX;
A constant EX = EY;
A constant EY = EZ;
A constant EZ = FA;
A constant FA = FB;
A constant FB = FC;
A constant FC = FD;
A constant FD = FE;
A constant FE = FF;
A constant FF = FG;
A constant FG = FH;
A constant FH = FI;
A constant FI = FJ;
A constant FJ = FK;
A constant FK = FL;
A constant FL = FM;
A constant FM = FN;
A constant FN = FO;
A constant FO = FP;
A constant FP = FQ;
A constant FQ = FR;
A constant FR = FS;
A constant FS = FT;
A constant FT = FU;
A constant FU = FV;
A constant FV = FW;
A constant FW = FX;
A constant FX = FY;
A constant FY = FZ;
A constant FZ = GA;
A constant GA = GB;
A constant GB = GC;
A constant GC = GD;
A constant GD = GE;
A constant GE = GF;
A constant GF = GG;
A constant GG = GH;
A constant GH = GI;
A constant GI = GJ;
A constant GJ = GK;
A constant GK = GL;
A constant GL = GM;
A constant GM = GN;
A constant GN = GO;
A constant GO = GP;
A constant GP = GQ;
A constant GQ = GR;
A constant GR = GS;
A constant GS = GT;
A constant GT = GU;
A constant GU = GV;
A constant GV = GW;
A constant GW = GX;
A constant GX = GY;
A constant GY = GZ;
A constant GZ = HA;
A constant HA = HB;
A constant HB = HC;
A constant HC = HD;
A constant HD = HE;
A constant HE = HF;
A constant HF = HG;
A constant HG = HH;
A constant HH = HI;
A constant HI = HJ;
A constant HJ = HK;
A constant HK = HL;
A constant HL = HM;
A constant HM = HN;
A constant HN = HO;
A constant HO = HP;
A constant HP = HQ;
A constant HQ = HR;
A constant HR = HS;
A constant HS = HT;
A constant HT = HU;
A constant HU = HV;
A constant HV = HW;
A constant HW = HX;
A constant HX = HY;
A constant HY = HZ;
A constant HZ = IA;
A constant IA = IB;
A constant IB = IC;
A constant IC = ID;
A constant ID = IE;
A constant IE = IF;
A constant IF = IG;
A constant IG = IH;
A constant IH = II;
A constant II = IJ;
A constant IJ = IK;
A constant IK = IL;
A constant IL = IM;
A constant IM = IN;
A constant IN = IO;
A constant IO = IP;
A constant IP = IQ;
A constant IQ = IR;
A constant IR = IS;
A constant IS = IT;
A constant IT = IU;
A constant IU = IV;
A constant IV = IW;
A constant IW = IX;
A constant IX = IY;
A constant IY = IZ;
A constant IZ = JA;
A constant JA = JB;
A constant JB = JC;
A constant JC = JD;
A constant JD = JE;
A constant JE = JF;
A constant JF = JG;
A constant JG = JH;
A constant JH = JI;
A constant JI = JJ;
A constant JJ = JK;
A constant JK = JL;
A constant JL = JM;
A constant JM = JN;
A constant JN = JO;
A constant JO = JP;
A constant JP = JQ;
A constant JQ = JR;
A constant JR = JS;
A constant JS = JT;
A constant JT = JU;
A constant JU = JV;
A constant JV = JW;
A constant JW = JX;
A constant JX = A(0x00);
}
// ----
// DeclarationError: (6105-6123): Variable definition exhausting cyclic dependency validator.

View File

@ -0,0 +1,135 @@
contract A {}
contract Main {
A constant B = C;
A constant C = D;
A constant D = E;
A constant E = F;
A constant F = G;
A constant G = H;
A constant H = I;
A constant I = J;
A constant J = K;
A constant K = L;
A constant L = M;
A constant M = N;
A constant N = O;
A constant O = P;
A constant P = Q;
A constant Q = R;
A constant R = S;
A constant S = T;
A constant T = U;
A constant U = V;
A constant V = W;
A constant W = X;
A constant X = Y;
A constant Y = Z;
A constant Z = BA;
A constant BA = BB;
A constant BB = BC;
A constant BC = BD;
A constant BD = BE;
A constant BE = BF;
A constant BF = BG;
A constant BG = BH;
A constant BH = BI;
A constant BI = BJ;
A constant BJ = BK;
A constant BK = BL;
A constant BL = BM;
A constant BM = BN;
A constant BN = BO;
A constant BO = BP;
A constant BP = BQ;
A constant BQ = BR;
A constant BR = BS;
A constant BS = BT;
A constant BT = BU;
A constant BU = BV;
A constant BV = BW;
A constant BW = BX;
A constant BX = BY;
A constant BY = BZ;
A constant BZ = CA;
A constant CA = CB;
A constant CB = CC;
A constant CC = CD;
A constant CD = CE;
A constant CE = CF;
A constant CF = CG;
A constant CG = CH;
A constant CH = CI;
A constant CI = CJ;
A constant CJ = CK;
A constant CK = CL;
A constant CL = CM;
A constant CM = CN;
A constant CN = CO;
A constant CO = CP;
A constant CP = CQ;
A constant CQ = CR;
A constant CR = CS;
A constant CS = CT;
A constant CT = CU;
A constant CU = CV;
A constant CV = CW;
A constant CW = CX;
A constant CX = CY;
A constant CY = CZ;
A constant CZ = DA;
A constant DA = DB;
A constant DB = DC;
A constant DC = DD;
A constant DD = DE;
A constant DE = DF;
A constant DF = DG;
A constant DG = DH;
A constant DH = DI;
A constant DI = DJ;
A constant DJ = DK;
A constant DK = DL;
A constant DL = DM;
A constant DM = DN;
A constant DN = DO;
A constant DO = DP;
A constant DP = DQ;
A constant DQ = DR;
A constant DR = DS;
A constant DS = DT;
A constant DT = DU;
A constant DU = DV;
A constant DV = DW;
A constant DW = DX;
A constant DX = DY;
A constant DY = DZ;
A constant DZ = EA;
A constant EA = EB;
A constant EB = EC;
A constant EC = ED;
A constant ED = EE;
A constant EE = EF;
A constant EF = EG;
A constant EG = EH;
A constant EH = EI;
A constant EI = EJ;
A constant EJ = EK;
A constant EK = EL;
A constant EL = EM;
A constant EM = EN;
A constant EN = EO;
A constant EO = EP;
A constant EP = EQ;
A constant EQ = ER;
A constant ER = ES;
A constant ES = ET;
A constant ET = EU;
A constant EU = EV;
A constant EV = EW;
A constant EW = EX;
A constant EX = EY;
A constant EY = EZ;
A constant EZ = FA;
A constant FA = FB;
A constant FB = FC;
A constant FC = A(0x00);
}

View File

@ -0,0 +1,260 @@
contract Main {
struct B { C m; }
struct C { D m; }
struct D { E m; }
struct E { F m; }
struct F { G m; }
struct G { H m; }
struct H { I m; }
struct I { J m; }
struct J { K m; }
struct K { L m; }
struct L { M m; }
struct M { N m; }
struct N { O m; }
struct O { P m; }
struct P { Q m; }
struct Q { R m; }
struct R { S m; }
struct S { T m; }
struct T { U m; }
struct U { V m; }
struct V { W m; }
struct W { X m; }
struct X { Y m; }
struct Y { Z m; }
struct Z { BA m; }
struct BA { BB m; }
struct BB { BC m; }
struct BC { BD m; }
struct BD { BE m; }
struct BE { BF m; }
struct BF { BG m; }
struct BG { BH m; }
struct BH { BI m; }
struct BI { BJ m; }
struct BJ { BK m; }
struct BK { BL m; }
struct BL { BM m; }
struct BM { BN m; }
struct BN { BO m; }
struct BO { BP m; }
struct BP { BQ m; }
struct BQ { BR m; }
struct BR { BS m; }
struct BS { BT m; }
struct BT { BU m; }
struct BU { BV m; }
struct BV { BW m; }
struct BW { BX m; }
struct BX { BY m; }
struct BY { BZ m; }
struct BZ { CA m; }
struct CA { CB m; }
struct CB { CC m; }
struct CC { CD m; }
struct CD { CE m; }
struct CE { CF m; }
struct CF { CG m; }
struct CG { CH m; }
struct CH { CI m; }
struct CI { CJ m; }
struct CJ { CK m; }
struct CK { CL m; }
struct CL { CM m; }
struct CM { CN m; }
struct CN { CO m; }
struct CO { CP m; }
struct CP { CQ m; }
struct CQ { CR m; }
struct CR { CS m; }
struct CS { CT m; }
struct CT { CU m; }
struct CU { CV m; }
struct CV { CW m; }
struct CW { CX m; }
struct CX { CY m; }
struct CY { CZ m; }
struct CZ { DA m; }
struct DA { DB m; }
struct DB { DC m; }
struct DC { DD m; }
struct DD { DE m; }
struct DE { DF m; }
struct DF { DG m; }
struct DG { DH m; }
struct DH { DI m; }
struct DI { DJ m; }
struct DJ { DK m; }
struct DK { DL m; }
struct DL { DM m; }
struct DM { DN m; }
struct DN { DO m; }
struct DO { DP m; }
struct DP { DQ m; }
struct DQ { DR m; }
struct DR { DS m; }
struct DS { DT m; }
struct DT { DU m; }
struct DU { DV m; }
struct DV { DW m; }
struct DW { DX m; }
struct DX { DY m; }
struct DY { DZ m; }
struct DZ { EA m; }
struct EA { EB m; }
struct EB { EC m; }
struct EC { ED m; }
struct ED { EE m; }
struct EE { EF m; }
struct EF { EG m; }
struct EG { EH m; }
struct EH { EI m; }
struct EI { EJ m; }
struct EJ { EK m; }
struct EK { EL m; }
struct EL { EM m; }
struct EM { EN m; }
struct EN { EO m; }
struct EO { EP m; }
struct EP { EQ m; }
struct EQ { ER m; }
struct ER { ES m; }
struct ES { ET m; }
struct ET { EU m; }
struct EU { EV m; }
struct EV { EW m; }
struct EW { EX m; }
struct EX { EY m; }
struct EY { EZ m; }
struct EZ { FA m; }
struct FA { FB m; }
struct FB { FC m; }
struct FC { FD m; }
struct FD { FE m; }
struct FE { FF m; }
struct FF { FG m; }
struct FG { FH m; }
struct FH { FI m; }
struct FI { FJ m; }
struct FJ { FK m; }
struct FK { FL m; }
struct FL { FM m; }
struct FM { FN m; }
struct FN { FO m; }
struct FO { FP m; }
struct FP { FQ m; }
struct FQ { FR m; }
struct FR { FS m; }
struct FS { FT m; }
struct FT { FU m; }
struct FU { FV m; }
struct FV { FW m; }
struct FW { FX m; }
struct FX { FY m; }
struct FY { FZ m; }
struct FZ { GA m; }
struct GA { GB m; }
struct GB { GC m; }
struct GC { GD m; }
struct GD { GE m; }
struct GE { GF m; }
struct GF { GG m; }
struct GG { GH m; }
struct GH { GI m; }
struct GI { GJ m; }
struct GJ { GK m; }
struct GK { GL m; }
struct GL { GM m; }
struct GM { GN m; }
struct GN { GO m; }
struct GO { GP m; }
struct GP { GQ m; }
struct GQ { GR m; }
struct GR { GS m; }
struct GS { GT m; }
struct GT { GU m; }
struct GU { GV m; }
struct GV { GW m; }
struct GW { GX m; }
struct GX { GY m; }
struct GY { GZ m; }
struct GZ { HA m; }
struct HA { HB m; }
struct HB { HC m; }
struct HC { HD m; }
struct HD { HE m; }
struct HE { HF m; }
struct HF { HG m; }
struct HG { HH m; }
struct HH { HI m; }
struct HI { HJ m; }
struct HJ { HK m; }
struct HK { HL m; }
struct HL { HM m; }
struct HM { HN m; }
struct HN { HO m; }
struct HO { HP m; }
struct HP { HQ m; }
struct HQ { HR m; }
struct HR { HS m; }
struct HS { HT m; }
struct HT { HU m; }
struct HU { HV m; }
struct HV { HW m; }
struct HW { HX m; }
struct HX { HY m; }
struct HY { HZ m; }
struct HZ { IA m; }
struct IA { IB m; }
struct IB { IC m; }
struct IC { ID m; }
struct ID { IE m; }
struct IE { IF m; }
struct IF { IG m; }
struct IG { IH m; }
struct IH { II m; }
struct II { IJ m; }
struct IJ { IK m; }
struct IK { IL m; }
struct IL { IM m; }
struct IM { IN m; }
struct IN { IO m; }
struct IO { IP m; }
struct IP { IQ m; }
struct IQ { IR m; }
struct IR { IS m; }
struct IS { IT m; }
struct IT { IU m; }
struct IU { IV m; }
struct IV { IW m; }
struct IW { IX m; }
struct IX { IY m; }
struct IY { IZ m; }
struct IZ { JA m; }
struct JA { JB m; }
struct JB { JC m; }
struct JC { JD m; }
struct JD { JE m; }
struct JE { JF m; }
struct JF { JG m; }
struct JG { JH m; }
struct JH { JI m; }
struct JI { JJ m; }
struct JJ { JK m; }
struct JK { JL m; }
struct JL { JM m; }
struct JM { JN m; }
struct JN { JO m; }
struct JO { JP m; }
struct JP { JQ m; }
struct JQ { JR m; }
struct JR { JS m; }
struct JS { JT m; }
struct JT { JU m; }
struct JU { JV m; }
struct JV { JW m; }
struct JW { int i; }
}
// ----
// DeclarationError: (6091-6111): Struct definition exhausting cyclic dependency validator.

View File

@ -0,0 +1,134 @@
contract Main {
struct B { C m; }
struct C { D m; }
struct D { E m; }
struct E { F m; }
struct F { G m; }
struct G { H m; }
struct H { I m; }
struct I { J m; }
struct J { K m; }
struct K { L m; }
struct L { M m; }
struct M { N m; }
struct N { O m; }
struct O { P m; }
struct P { Q m; }
struct Q { R m; }
struct R { S m; }
struct S { T m; }
struct T { U m; }
struct U { V m; }
struct V { W m; }
struct W { X m; }
struct X { Y m; }
struct Y { Z m; }
struct Z { BA m; }
struct BA { BB m; }
struct BB { BC m; }
struct BC { BD m; }
struct BD { BE m; }
struct BE { BF m; }
struct BF { BG m; }
struct BG { BH m; }
struct BH { BI m; }
struct BI { BJ m; }
struct BJ { BK m; }
struct BK { BL m; }
struct BL { BM m; }
struct BM { BN m; }
struct BN { BO m; }
struct BO { BP m; }
struct BP { BQ m; }
struct BQ { BR m; }
struct BR { BS m; }
struct BS { BT m; }
struct BT { BU m; }
struct BU { BV m; }
struct BV { BW m; }
struct BW { BX m; }
struct BX { BY m; }
struct BY { BZ m; }
struct BZ { CA m; }
struct CA { CB m; }
struct CB { CC m; }
struct CC { CD m; }
struct CD { CE m; }
struct CE { CF m; }
struct CF { CG m; }
struct CG { CH m; }
struct CH { CI m; }
struct CI { CJ m; }
struct CJ { CK m; }
struct CK { CL m; }
struct CL { CM m; }
struct CM { CN m; }
struct CN { CO m; }
struct CO { CP m; }
struct CP { CQ m; }
struct CQ { CR m; }
struct CR { CS m; }
struct CS { CT m; }
struct CT { CU m; }
struct CU { CV m; }
struct CV { CW m; }
struct CW { CX m; }
struct CX { CY m; }
struct CY { CZ m; }
struct CZ { DA m; }
struct DA { DB m; }
struct DB { DC m; }
struct DC { DD m; }
struct DD { DE m; }
struct DE { DF m; }
struct DF { DG m; }
struct DG { DH m; }
struct DH { DI m; }
struct DI { DJ m; }
struct DJ { DK m; }
struct DK { DL m; }
struct DL { DM m; }
struct DM { DN m; }
struct DN { DO m; }
struct DO { DP m; }
struct DP { DQ m; }
struct DQ { DR m; }
struct DR { DS m; }
struct DS { DT m; }
struct DT { DU m; }
struct DU { DV m; }
struct DV { DW m; }
struct DW { DX m; }
struct DX { DY m; }
struct DY { DZ m; }
struct DZ { EA m; }
struct EA { EB m; }
struct EB { EC m; }
struct EC { ED m; }
struct ED { EE m; }
struct EE { EF m; }
struct EF { EG m; }
struct EG { EH m; }
struct EH { EI m; }
struct EI { EJ m; }
struct EJ { EK m; }
struct EK { EL m; }
struct EL { EM m; }
struct EM { EN m; }
struct EN { EO m; }
struct EO { EP m; }
struct EP { EQ m; }
struct EQ { ER m; }
struct ER { ES m; }
struct ES { ET m; }
struct ET { EU m; }
struct EU { EV m; }
struct EV { EW m; }
struct EW { EX m; }
struct EX { EY m; }
struct EY { EZ m; }
struct EZ { FA m; }
struct FA { FB m; }
struct FB { FC m; }
struct FC { int i; }
}