-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from Consensys/cfg
Cfg
- Loading branch information
Showing
12 changed files
with
315 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
.decl dominate(pred: id, succ: id) | ||
|
||
/// Dominate inherits from dominateStmt for statements | ||
dominate(pred, succ) :- | ||
dominateStmt(pred, succ). | ||
|
||
/// If statement A dominates statement B, then all ExpressionStatement in | ||
/// statement A dominate all expressions in statement B | ||
dominate(pred, succ) :- | ||
dominateStmt(A, B), | ||
ancestor(A, pred), | ||
Expression(pred), | ||
ancestor(B, succ), | ||
Expression(succ). | ||
|
||
/// All expressions "syntactically" inside a statement must evaluate before its | ||
/// conisdered "executed" | ||
dominate(pred, succ) :- | ||
Statement(succ), | ||
ancestor(succ, pred), | ||
Expression(pred). | ||
|
||
/// All expressions "syntactically" inside another expression must finish evaluating | ||
/// before the parent expression has evaluated | ||
dominate(pred, succ) :- | ||
Expression(succ), | ||
ancestor(succ, pred), | ||
Expression(pred). | ||
|
||
/// Assignment | ||
dominate(pred, succ) :- | ||
Assignment(_, _, _, _, succ, pred). | ||
|
||
/// BinaryOperation | ||
dominate(pred, succ) :- | ||
BinaryOperation(boId, _, _, _, pred, succ, _, _). | ||
|
||
/// Conditional | ||
dominate(pred, succ) :- | ||
Conditional(_, _, _, pred, succ, _). | ||
|
||
dominate(pred, succ) :- | ||
Conditional(_, _, _, pred, _, succ). | ||
|
||
/// FunctionCall | ||
dominate(pred, succ) :- | ||
FunctionCall(fcId, _, _, _, _), | ||
FunctionCall_vArguments(fcId, pred, i), | ||
FunctionCall_vArguments(fcId, succ, i + 1). | ||
|
||
/// IndexAccess | ||
dominate(pred, succ) :- | ||
IndexAccess(_, _, _, succ, pred, 1). | ||
|
||
/// IndexRangeAccess | ||
dominate(pred, succ) :- | ||
IndexRangeAccess(_, _, _, succ, pred, 1, _, _). | ||
|
||
dominate(pred, succ) :- | ||
IndexRangeAccess(_, _, _, succ, _, _, pred, 1). | ||
|
||
/// TupleExpression | ||
dominate(pred, succ) :- | ||
TupleExpression(tId, _, _, _), | ||
TupleExpression_components(tId, pred, i), | ||
TupleExpression_components(tId, succ, i + 1). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Helper relation for expressing the CFG domination relation only between statements (and modifier invocations) | ||
.decl dominateStmt(pred: id, succ: id) | ||
|
||
// ForStatement | ||
// Initialization stmt comes before body | ||
dominateStmt(pred, succ) :- | ||
ForStatement(_, _, succ, pred, 1, _, _, _, _). | ||
|
||
// All stmts dominating the for dominate the init statement | ||
dominateStmt(pred, succ) :- | ||
ForStatement(fId, _, _, succ, 1, _, _, _, _), | ||
dominateStmt(pred, fId). | ||
|
||
// No init statement - all stmts dominating the for dominate the body | ||
dominateStmt(pred, succ) :- | ||
ForStatement(fId, _, succ, _, 0, _, _, _, _), | ||
dominateStmt(pred, fId). | ||
|
||
// TryStatement | ||
dominateStmt(pred, succ) :- | ||
TryStatement(tId, _, _), | ||
dominateStmt(pred, tId), | ||
TryStatement_vClauses(tId, cId, _), | ||
TryCatchClause(cId, _, _, succ, _, _). | ||
|
||
// BlockStatement | ||
dominateStmt(pred, succ) :- | ||
Block(bId, _), | ||
dominateStmt(pred, bId), | ||
Block_vStatements(bId, succ, 0). | ||
|
||
dominateStmt(pred, succ) :- | ||
Block(bId, _), | ||
Block_vStatements(bId, pred, i), | ||
Block_vStatements(bId, succ, i + 1). | ||
|
||
// UncheckedBlockStatement | ||
dominateStmt(pred, succ) :- | ||
UncheckedBlock(bId, _), | ||
dominateStmt(pred, bId), | ||
UncheckedBlock_vStatements(bId, succ, 0). | ||
|
||
dominateStmt(pred, succ) :- | ||
UncheckedBlock(bId, _), | ||
UncheckedBlock_vStatements(bId, pred, i), | ||
UncheckedBlock_vStatements(bId, succ, i + 1). | ||
|
||
// WhileStatement | ||
dominateStmt(pred, succ) :- | ||
WhileStatement(wId, _, _, succ), | ||
dominateStmt(pred, wId). | ||
|
||
// IfStatement | ||
dominateStmt(pred, succ) :- | ||
IfStatement(ifId, _, _, succ, _, _), | ||
dominateStmt(pred, ifId). | ||
|
||
dominateStmt(pred, succ) :- | ||
IfStatement(ifId, _, _, _, succ, 1), | ||
dominateStmt(pred, ifId). | ||
|
||
// DoWhile statement | ||
dominateStmt(pred, succ) :- | ||
DoWhileStatement(dwId, _, _, succ), | ||
dominateStmt(pred, dwId). | ||
|
||
// ModifierInvocations | ||
dominateStmt(pred, succ) :- | ||
FunctionDefinition(id, _, _, _, _, _, _, _, _, _, _, _, _, _, _), | ||
FunctionDefinition_vModifiers(id, pred, i), | ||
modifierInvocation_isModifier(pred), | ||
FunctionDefinition_vModifiers(id, succ, i + 1), | ||
modifierInvocation_isModifier(pred). | ||
|
||
// ModifierInvocations | ||
dominateStmt(pred, succ) :- | ||
FunctionDefinition(id, _, _, _, _, _, _, _, _, _, _, _, _, succ, 1), | ||
FunctionDefinition_vModifiers(id, pred, i), | ||
modifierInvocation_isModifier(pred). | ||
|
||
// Transitivity | ||
dominateStmt(pred, succ) :- | ||
dominateStmt(pred, x), | ||
dominateStmt(x, succ). | ||
|
||
// @todo Base constructors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import expect from "expect"; | ||
import fse from "fs-extra"; | ||
import * as sol from "solc-typed-ast"; | ||
import { OutputRelations, analyze } from "../src"; | ||
import { searchRecursive } from "../src/lib/utils"; | ||
|
||
const samples = searchRecursive("test/samples/analyses", (fileName) => fileName.endsWith(".json")); | ||
|
||
describe("Analyses", () => { | ||
for (const json of samples) { | ||
const sample = json.replace(".json", ".sol"); | ||
|
||
describe(sample, () => { | ||
let units: sol.SourceUnit[]; | ||
let expectedOutput: OutputRelations; | ||
let reader: sol.ASTReader; | ||
|
||
before(async () => { | ||
reader = new sol.ASTReader(); | ||
const result = await sol.compileSol(sample, "auto"); | ||
|
||
const data = result.data; | ||
const errors = sol.detectCompileErrors(data); | ||
|
||
expect(errors).toHaveLength(0); | ||
|
||
units = reader.read(data); | ||
|
||
expect(units.length).toBeGreaterThanOrEqual(1); | ||
|
||
expectedOutput = fse.readJSONSync(json, { | ||
encoding: "utf-8" | ||
}) as OutputRelations; | ||
}); | ||
|
||
it("Detectors produce expected results", async () => { | ||
const targetAnalyses = [...Object.keys(expectedOutput)]; | ||
const addtionalDL = targetAnalyses.map((x: string) => `.output ${x}`).join("\n"); | ||
|
||
const analysisResults = await analyze(units, addtionalDL); | ||
|
||
for (const [key, val] of Object.entries(expectedOutput)) { | ||
expect(analysisResults.get(key)).toEqual(val); | ||
} | ||
}); | ||
}); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"dominateStmt": [ | ||
[7, 13], | ||
[7, 14], | ||
[7, 17], | ||
[7, 18], | ||
[7, 19], | ||
[7, 23], | ||
[19, 23] | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
pragma solidity 0.8.17; | ||
|
||
contract Foo { | ||
function main() public { | ||
uint x = 1; | ||
if ( x > 0 ) { | ||
x++; | ||
} else { | ||
x--; | ||
} | ||
|
||
uint y = x; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"dominateStmt": [ | ||
[9, 13], | ||
[9, 20], | ||
[9, 26], | ||
[9, 27], | ||
[9, 28], | ||
[9, 30], | ||
[13, 20], | ||
[13, 26], | ||
[13, 27], | ||
[13, 28], | ||
[13, 30], | ||
[20, 26], | ||
[28, 30] | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
pragma solidity 0.8.17; | ||
|
||
contract Foo { | ||
function main() public returns (uint) { | ||
uint x = 1; | ||
uint sum = 0; | ||
|
||
while (x < 10) { | ||
sum += x; | ||
x = x + 1; | ||
} | ||
|
||
return sum; | ||
} | ||
} |