/src/solidity/libsolidity/formal/PredicateInstance.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | |
19 | | #include <libsolidity/formal/PredicateInstance.h> |
20 | | |
21 | | #include <libsolidity/formal/EncodingContext.h> |
22 | | #include <libsolidity/formal/SMTEncoder.h> |
23 | | |
24 | | using namespace std; |
25 | | using namespace solidity::util; |
26 | | using namespace solidity::smtutil; |
27 | | |
28 | | namespace solidity::frontend::smt |
29 | | { |
30 | | smtutil::Expression interfacePre(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context) |
31 | 10.3k | { |
32 | 10.3k | auto& state = _context.state(); |
33 | 10.3k | vector<smtutil::Expression> stateExprs{state.thisAddress(0), state.abi(0), state.crypto(0), state.state(0)}; |
34 | 10.3k | return _pred(stateExprs + initialStateVariables(_contract, _context)); |
35 | 10.3k | } |
36 | | |
37 | | smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context) |
38 | 31.2k | { |
39 | 31.2k | auto const& state = _context.state(); |
40 | 31.2k | vector<smtutil::Expression> stateExprs{state.thisAddress(0), state.abi(0), state.crypto(0), state.state()}; |
41 | 31.2k | return _pred(stateExprs + currentStateVariables(_contract, _context)); |
42 | 31.2k | } |
43 | | |
44 | | smtutil::Expression nondetInterface( |
45 | | Predicate const& _pred, |
46 | | ContractDefinition const& _contract, |
47 | | EncodingContext& _context, |
48 | | unsigned _preIdx, |
49 | | unsigned _postIdx) |
50 | 31.9k | { |
51 | 31.9k | auto const& state = _context.state(); |
52 | 31.9k | vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(), state.abi(), state.crypto()}; |
53 | 31.9k | return _pred( |
54 | 31.9k | stateExprs + |
55 | 31.9k | vector<smtutil::Expression>{_context.state().state(_preIdx)} + |
56 | 31.9k | stateVariablesAtIndex(_preIdx, _contract, _context) + |
57 | 31.9k | vector<smtutil::Expression>{_context.state().state(_postIdx)} + |
58 | 31.9k | stateVariablesAtIndex(_postIdx, _contract, _context) |
59 | 31.9k | ); |
60 | 31.9k | } |
61 | | |
62 | | smtutil::Expression constructor(Predicate const& _pred, EncodingContext& _context) |
63 | 114k | { |
64 | 114k | auto const& contract = dynamic_cast<ContractDefinition const&>(*_pred.programNode()); |
65 | 114k | if (auto const* constructor = contract.constructor()) |
66 | 12.9k | return _pred(currentFunctionVariablesForDefinition(*constructor, &contract, _context)); |
67 | | |
68 | 101k | auto& state = _context.state(); |
69 | 101k | vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state(0), state.state()}; |
70 | 101k | return _pred(stateExprs + initialStateVariables(contract, _context) + currentStateVariables(contract, _context)); |
71 | 114k | } |
72 | | |
73 | | smtutil::Expression constructorCall(Predicate const& _pred, EncodingContext& _context) |
74 | 11.8k | { |
75 | 11.8k | auto const& contract = dynamic_cast<ContractDefinition const&>(*_pred.programNode()); |
76 | 11.8k | if (auto const* constructor = contract.constructor()) |
77 | 1.28k | return _pred(currentFunctionVariablesForCall(*constructor, &contract, _context)); |
78 | | |
79 | 10.5k | auto& state = _context.state(); |
80 | 10.5k | vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state()}; |
81 | 10.5k | state.newState(); |
82 | 10.5k | stateExprs += vector<smtutil::Expression>{state.state()}; |
83 | 10.5k | stateExprs += currentStateVariables(contract, _context); |
84 | 10.5k | stateExprs += newStateVariables(contract, _context); |
85 | 10.5k | return _pred(stateExprs); |
86 | 11.8k | } |
87 | | |
88 | | smtutil::Expression function( |
89 | | Predicate const& _pred, |
90 | | ContractDefinition const* _contract, |
91 | | EncodingContext& _context |
92 | | ) |
93 | 66.9k | { |
94 | 66.9k | auto const& function = dynamic_cast<FunctionDefinition const&>(*_pred.programNode()); |
95 | 66.9k | return _pred(currentFunctionVariablesForDefinition(function, _contract, _context)); |
96 | 66.9k | } |
97 | | |
98 | | smtutil::Expression functionCall( |
99 | | Predicate const& _pred, |
100 | | ContractDefinition const* _contract, |
101 | | EncodingContext& _context |
102 | | ) |
103 | 11.6k | { |
104 | 11.6k | auto const& function = dynamic_cast<FunctionDefinition const&>(*_pred.programNode()); |
105 | 11.6k | return _pred(currentFunctionVariablesForCall(function, _contract, _context)); |
106 | 11.6k | } |
107 | | |
108 | | smtutil::Expression functionBlock( |
109 | | Predicate const& _pred, |
110 | | FunctionDefinition const& _function, |
111 | | ContractDefinition const* _contract, |
112 | | EncodingContext& _context |
113 | | ) |
114 | 113k | { |
115 | 113k | return _pred(currentBlockVariables(_function, _contract, _context)); |
116 | 113k | } |
117 | | |
118 | | /// Helpers |
119 | | |
120 | | vector<smtutil::Expression> initialStateVariables(ContractDefinition const& _contract, EncodingContext& _context) |
121 | 305k | { |
122 | 305k | return stateVariablesAtIndex(0, _contract, _context); |
123 | 305k | } |
124 | | |
125 | | vector<smtutil::Expression> stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract, EncodingContext& _context) |
126 | 369k | { |
127 | 369k | return applyMap( |
128 | 369k | SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), |
129 | 369k | [&](auto _var) { return _context.variable(*_var)->valueAtIndex(_index); } |
130 | 369k | ); |
131 | 369k | } |
132 | | |
133 | | vector<smtutil::Expression> currentStateVariables(ContractDefinition const& _contract, EncodingContext& _context) |
134 | 349k | { |
135 | 349k | return applyMap( |
136 | 349k | SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), |
137 | 349k | [&](auto _var) { return _context.variable(*_var)->currentValue(); } |
138 | 349k | ); |
139 | 349k | } |
140 | | |
141 | | vector<smtutil::Expression> newStateVariables(ContractDefinition const& _contract, EncodingContext& _context) |
142 | 23.4k | { |
143 | 23.4k | return applyMap( |
144 | 23.4k | SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), |
145 | 23.4k | [&](auto _var) { return _context.variable(*_var)->increaseIndex(); } |
146 | 23.4k | ); |
147 | 23.4k | } |
148 | | |
149 | | vector<smtutil::Expression> currentFunctionVariablesForDefinition( |
150 | | FunctionDefinition const& _function, |
151 | | ContractDefinition const* _contract, |
152 | | EncodingContext& _context |
153 | | ) |
154 | 193k | { |
155 | 193k | auto& state = _context.state(); |
156 | 193k | vector<smtutil::Expression> exprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state(0)}; |
157 | 193k | exprs += _contract ? initialStateVariables(*_contract, _context) : vector<smtutil::Expression>{}; |
158 | 193k | exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->valueAtIndex(0); }); |
159 | 193k | exprs += vector<smtutil::Expression>{state.state()}; |
160 | 193k | exprs += _contract ? currentStateVariables(*_contract, _context) : vector<smtutil::Expression>{}; |
161 | 193k | exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); |
162 | 193k | exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); |
163 | 193k | return exprs; |
164 | 193k | } |
165 | | |
166 | | vector<smtutil::Expression> currentFunctionVariablesForCall( |
167 | | FunctionDefinition const& _function, |
168 | | ContractDefinition const* _contract, |
169 | | EncodingContext& _context |
170 | | ) |
171 | 12.9k | { |
172 | 12.9k | auto& state = _context.state(); |
173 | 12.9k | vector<smtutil::Expression> exprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state()}; |
174 | 12.9k | exprs += _contract ? currentStateVariables(*_contract, _context) : vector<smtutil::Expression>{}; |
175 | 12.9k | exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); |
176 | | |
177 | 12.9k | state.newState(); |
178 | | |
179 | 12.9k | exprs += vector<smtutil::Expression>{state.state()}; |
180 | 12.9k | exprs += _contract ? newStateVariables(*_contract, _context) : vector<smtutil::Expression>{}; |
181 | 12.9k | exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->increaseIndex(); }); |
182 | 12.9k | exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); |
183 | 12.9k | return exprs; |
184 | 12.9k | } |
185 | | |
186 | | vector<smtutil::Expression> currentBlockVariables(FunctionDefinition const& _function, ContractDefinition const* _contract, EncodingContext& _context) |
187 | 113k | { |
188 | 113k | return currentFunctionVariablesForDefinition(_function, _contract, _context) + |
189 | 113k | applyMap( |
190 | 113k | SMTEncoder::localVariablesIncludingModifiers(_function, _contract), |
191 | 113k | [&](auto _var) { return _context.variable(*_var)->currentValue(); } |
192 | 113k | ); |
193 | 113k | } |
194 | | |
195 | | } |