|
| 1 | +--- |
| 2 | +mode: 'agent' |
| 3 | +--- |
| 4 | + |
| 5 | +Given a AST class or set of classes, create the various CFG related classes. |
| 6 | +This includes the following: |
| 7 | +- ControlFlowGraphImpl Tree class |
| 8 | +- CfgNodes classes for each AST Node |
| 9 | + |
| 10 | +**Guidelines:** |
| 11 | + |
| 12 | +- Classify the AST class into the appropriate Control Flow Graph (CFG) class. |
| 13 | +- Implement the `ControlFlowGraphImpl.qll` class if it does not exist. |
| 14 | +- Implement the `CfgNodes` classes for each AST Node, ensuring that they follow the naming conventions and structure outlined below. |
| 15 | +- All ControlFlowGraph Tree classes should be in the `ControlFlowGraphImpl.qll` file. |
| 16 | +- All CfgNodes classes should be in the `CfgNodes.qll` file. |
| 17 | + |
| 18 | +## Reading AST Implementaion |
| 19 | + |
| 20 | +All public AST classes are are in the `ql/lib/codeql/bicep/ast/*.qll` files. |
| 21 | +Read the classes implementation and documentation to understand the structure and relationships of the AST nodes. |
| 22 | + |
| 23 | +## Classification |
| 24 | + |
| 25 | +The AST classes should be classified into the following categories based on their structure and relationships: |
| 26 | + |
| 27 | +- **LeafTree**: |
| 28 | + - AST nodes that do not have children, such as literals and identifiers. |
| 29 | +- **StandardPostOrderTree**: |
| 30 | + - AST nodes that are traversed in a post-order manner |
| 31 | +- **PreOrderTree**: |
| 32 | + - AST nodes that are traversed in a pre-order manner, meaning the node itself is visited before its children. |
| 33 | +- **PostOrderTree**: |
| 34 | + - AST nodes that are traversed in a post-order manner, |
| 35 | + |
| 36 | +Once the classification is done, the appropriate Control Flow Graph (CFG) class should be created. |
| 37 | + |
| 38 | +## Control Flow Graph Implementaion |
| 39 | + |
| 40 | +If you are asked to implement any Control Flow Graph (CFG) classes or predicates, you should follow the guidelines below. |
| 41 | +The Control Flow Graph (CFG) is a representation of all paths that might be traversed through a program during its execution. |
| 42 | +The Control Flow Graph library is in `ql/lib/codeql/**/controlflow/internal/ControlFlowGraphImpl.qll` |
| 43 | + |
| 44 | +An AST node can only be represented as a single Control Flow Graph node class. |
| 45 | +All Control Flow Graph node classes should have a suffix of `Tree` to indicate that they are part of the Control Flow Graph library. |
| 46 | +Example classes include `ExprTree`, `StmtsTree`, and `ProgramTree`. |
| 47 | + |
| 48 | +Use the `first()` and `last()` predicates to indicate the first and last nodes in the control flow. |
| 49 | + |
| 50 | +### CFG LeafTree Nodes |
| 51 | + |
| 52 | +The LeafTree Nodes are a part of the Control Flow Graph library and represent an end nodes in the CFG. |
| 53 | +LeafTree Nodes are used to represent nodes in the CFG that do not have any children, meaning they are the end points of a path in the graph. |
| 54 | + |
| 55 | +All Literals AST types are represented as LeafTree Nodes. |
| 56 | + |
| 57 | +### CFG StandardPostOrderTree Nodes |
| 58 | + |
| 59 | +The StandardPostOrderTree Nodes are a part of the Control Flow Graph library and represent the nodes in the CFG that are traversed in a post-order manner. |
| 60 | +StandardPostOrderTree Nodes are used to represent nodes in the CFG that are traversed in a post-order manner, meaning that the children of a node are visited before the node itself. |
| 61 | + |
| 62 | +Expressions and statements in the CFG are represented as StandardPostOrderTree Nodes. |
| 63 | + |
| 64 | +If an expression or statement uses a predicate for accessing its children it should be used. |
| 65 | +If an expression or statement does not have a predicate for accessing its children, the `getChild(i)` method should be used to access the children. |
| 66 | + |
| 67 | +The following predicates should be implemented and overrided: |
| 68 | +- `override AstNode getChildNode(int i)` |
| 69 | + - to get the child node at index `i`. |
| 70 | + - result should be the child node at index `i`. |
| 71 | + - If a node has multiple nodes, add the children in the order of execution in a Bicep program |
| 72 | + |
| 73 | +**StandardPostOrderTree Class Example:** |
| 74 | + |
| 75 | +```codeql |
| 76 | +class ${AstNode}Tree extends StandardPostOrderTree instanceof ${AstNode} { |
| 77 | + override AstNode getChildNode(int i) { |
| 78 | + i = 0 and result = super.getAChild() |
| 79 | + } |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +### CFG PreOrderTree Nodes |
| 84 | + |
| 85 | +The PreOrderTree Nodes are a part of the Control Flow Graph library and represent the nodes in the CFG that are traversed in a pre-order manner. |
| 86 | +PreOrderTree Nodes are used to represent nodes in the CFG that are traversed in a pre-order manner, meaning that the node itself is visited before its children. |
| 87 | + |
| 88 | +The following predicates should be implemented and overrided: |
| 89 | + |
| 90 | +- `final override predicate propagatesAbnormal(AstNode child)` |
| 91 | + - to indicate if the node propagates abnormal control flow to its child. |
| 92 | + - child should be matched with the child node of the AST node. |
| 93 | +- `override predicate succ(AstNode pred, AstNode succ, Completion c)` |
| 94 | + - to indicate the successor of the node. |
| 95 | + - `pred` should be the predecessor node. |
| 96 | + - `succ` should be the successor node. |
| 97 | + - `c` should be the completion of the successor node. |
| 98 | +- `override predicate last(AstNode node, Completion c)` |
| 99 | + - to indicate if the node is the last node in the control flow. |
| 100 | + - `node` should be the node to check. |
| 101 | + - `c` should be the completion of the node. |
| 102 | + |
| 103 | +**PreOrderTree Class Example:** |
| 104 | + |
| 105 | +```codeql |
| 106 | +class ${AstNode}Tree extends PreOrderTree instanceof ${AstNode} { |
| 107 | + final override predicate propagatesAbnormal(AstNode child) { child = super.getIdentifier() } |
| 108 | +
|
| 109 | + override predicate succ(AstNode pred, AstNode succ, Completion c) { |
| 110 | + // Start with the identifier |
| 111 | + pred = this and first(super.getIdentifier(), succ) and completionIsSimple(c) |
| 112 | + or |
| 113 | + last(super.getIdentifier(), pred, c) and first(super.getDefaultValue(), succ) and completionIsNormal(c) |
| 114 | + } |
| 115 | +
|
| 116 | + override predicate last(AstNode node, Completion c) { |
| 117 | + node = super.getDefaultValue() and completionIsNormal(c) |
| 118 | + } |
| 119 | +} |
| 120 | +``` |
| 121 | + |
| 122 | +Check and validate if a CFG Tree class is present in the `ControlFlowGraphImpl.qll` file. |
| 123 | +If on Tree class is not present, implement the class for the desired node. |
| 124 | + |
| 125 | +## CfgNodes Implementaion |
| 126 | + |
| 127 | +Check and validate if the `${AstNode}ChildMapping` or `${AstNode}CfgNode` classes are in the `CfgNodes.qll` file. |
| 128 | +Exprs and Stmts should be under there modules such as `ExprNodes` and `StmtsNodes`. |
| 129 | +All CfgNodes classes either end with `CfgNode` or `ChildMapping`. |
| 130 | + |
| 131 | +For Expr based AST Nodes: |
| 132 | +- Create a `ChildMapping` abstract class inheriting both `ExprChildMapping` and `${AstNode}` |
| 133 | + - Override the `relevantChild(AstNode n)` prediate |
| 134 | +- Create a class called `${AstNode}CfgNode` which extends the `ExprCfgNode` |
| 135 | + - override `e` with the `${AstNode}ChildMapping` |
| 136 | + - implement `final override ${AstNode} getExpr() { result = super.getExpr() } |
| 137 | + |
| 138 | +All Expr's with Left and Right Operations, implement final predicates returning `ExprCfgNode` |
0 commit comments