MCPcopy Create free account
hub / github.com/argotorg/solidity / checkUninitializedAccess

Method checkUninitializedAccess

libsolidity/analysis/ControlFlowAnalyzer.cpp:63–194  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

61
62
63void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNode const* _exit, bool _emptyBody, std::optional<std::string> _contractName)
64{
65 struct NodeInfo
66 {
67 std::set<VariableDeclaration const*> unassignedVariablesAtEntry;
68 std::set<VariableDeclaration const*> unassignedVariablesAtExit;
69 std::set<VariableOccurrence const*> uninitializedVariableAccesses;
70 /// Propagate the information from another node to this node.
71 /// To be used to propagate information from a node to its exit nodes.
72 /// Returns true, if new variables were added and thus the current node has
73 /// to be traversed again.
74 bool propagateFrom(NodeInfo const& _entryNode)
75 {
76 size_t previousUnassignedVariablesAtEntry = unassignedVariablesAtEntry.size();
77 size_t previousUninitializedVariableAccesses = uninitializedVariableAccesses.size();
78 unassignedVariablesAtEntry += _entryNode.unassignedVariablesAtExit;
79 uninitializedVariableAccesses += _entryNode.uninitializedVariableAccesses;
80 return
81 unassignedVariablesAtEntry.size() > previousUnassignedVariablesAtEntry ||
82 uninitializedVariableAccesses.size() > previousUninitializedVariableAccesses
83 ;
84 }
85 };
86 std::map<CFGNode const*, NodeInfo> nodeInfos;
87 std::set<CFGNode const*> nodesToTraverse;
88 nodesToTraverse.insert(_entry);
89
90 // Walk all paths starting from the nodes in ``nodesToTraverse`` until ``NodeInfo::propagateFrom``
91 // returns false for all exits, i.e. until all paths have been walked with maximal sets of unassigned
92 // variables and accesses.
93 while (!nodesToTraverse.empty())
94 {
95 CFGNode const* currentNode = *nodesToTraverse.begin();
96 nodesToTraverse.erase(nodesToTraverse.begin());
97
98 auto& nodeInfo = nodeInfos[currentNode];
99 auto unassignedVariables = nodeInfo.unassignedVariablesAtEntry;
100 for (auto const& variableOccurrence: currentNode->variableOccurrences)
101 {
102 switch (variableOccurrence.kind())
103 {
104 case VariableOccurrence::Kind::Assignment:
105 unassignedVariables.erase(&variableOccurrence.declaration());
106 break;
107 case VariableOccurrence::Kind::InlineAssembly:
108 // We consider all variables referenced in inline assembly as accessed.
109 // So far any reference is enough, but we might want to actually analyze
110 // the control flow in the assembly at some point.
111 case VariableOccurrence::Kind::Access:
112 case VariableOccurrence::Kind::Return:
113 if (unassignedVariables.count(&variableOccurrence.declaration()))
114 {
115 // Merely store the unassigned access. We do not generate an error right away, since this
116 // path might still always revert. It is only an error if this is propagated to the exit
117 // node of the function (i.e. there is a path with an uninitialized access).
118 nodeInfo.uninitializedVariableAccesses.insert(&variableOccurrence);
119 }
120 break;

Callers

nothing calls this directly

Calls 15

valueOrNullptrFunction · 0.85
insertMethod · 0.80
eraseMethod · 0.80
declarationMethod · 0.80
propagateFromMethod · 0.80
typeErrorMethod · 0.80
emptyMethod · 0.45
beginMethod · 0.45
kindMethod · 0.45
countMethod · 0.45
endMethod · 0.45
appendMethod · 0.45

Tested by

no test coverage detected