/src/solidity/libsolidity/formal/SymbolicVariables.h
Line | Count | Source |
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 | | #pragma once |
20 | | |
21 | | #include <libsolidity/formal/SSAVariable.h> |
22 | | #include <libsolidity/ast/Types.h> |
23 | | #include <libsolidity/ast/TypeProvider.h> |
24 | | |
25 | | #include <libsmtutil/SolverInterface.h> |
26 | | |
27 | | #include <map> |
28 | | #include <memory> |
29 | | |
30 | | namespace solidity::frontend::smt |
31 | | { |
32 | | |
33 | | class EncodingContext; |
34 | | class Type; |
35 | | |
36 | | /** |
37 | | * This abstract class represents the symbolic version of a program variable. |
38 | | */ |
39 | | class SymbolicVariable |
40 | | { |
41 | | public: |
42 | | SymbolicVariable( |
43 | | frontend::Type const* _type, |
44 | | frontend::Type const* _originalType, |
45 | | std::string _uniqueName, |
46 | | EncodingContext& _context |
47 | | ); |
48 | | SymbolicVariable( |
49 | | smtutil::SortPointer _sort, |
50 | | std::string _uniqueName, |
51 | | EncodingContext& _context |
52 | | ); |
53 | | |
54 | | SymbolicVariable(SymbolicVariable&&) = default; |
55 | | |
56 | 544k | virtual ~SymbolicVariable() = default; |
57 | | |
58 | | virtual smtutil::Expression currentValue(frontend::Type const* _targetType = nullptr) const; |
59 | | std::string currentName() const; |
60 | | virtual smtutil::Expression valueAtIndex(unsigned _index) const; |
61 | | virtual std::string nameAtIndex(unsigned _index) const; |
62 | | virtual smtutil::Expression resetIndex(); |
63 | | virtual smtutil::Expression setIndex(unsigned _index); |
64 | | virtual smtutil::Expression increaseIndex(); |
65 | | virtual smtutil::Expression operator()(std::vector<smtutil::Expression> const& /*_arguments*/) const |
66 | 0 | { |
67 | 0 | solAssert(false, "Function application to non-function."); |
68 | 0 | } |
69 | | |
70 | 0 | unsigned index() const { return m_ssa->index(); } |
71 | 65.2k | unsigned& index() { return m_ssa->index(); } |
72 | | |
73 | 1.53M | smtutil::SortPointer const& sort() const { return m_sort; } |
74 | 246k | frontend::Type const* type() const { return m_type; } |
75 | 1.20k | frontend::Type const* originalType() const { return m_originalType; } |
76 | | |
77 | | protected: |
78 | | std::string uniqueSymbol(unsigned _index) const; |
79 | | |
80 | | /// SMT sort. |
81 | | smtutil::SortPointer m_sort; |
82 | | /// Solidity type, used for size and range in number types. |
83 | | frontend::Type const* m_type; |
84 | | /// Solidity original type, used for type conversion if necessary. |
85 | | frontend::Type const* m_originalType; |
86 | | std::string m_uniqueName; |
87 | | EncodingContext& m_context; |
88 | | std::unique_ptr<SSAVariable> m_ssa; |
89 | | }; |
90 | | |
91 | | /** |
92 | | * Specialization of SymbolicVariable for Bool |
93 | | */ |
94 | | class SymbolicBoolVariable: public SymbolicVariable |
95 | | { |
96 | | public: |
97 | | SymbolicBoolVariable( |
98 | | frontend::Type const* _type, |
99 | | std::string _uniqueName, |
100 | | EncodingContext& _context |
101 | | ); |
102 | | }; |
103 | | |
104 | | /** |
105 | | * Specialization of SymbolicVariable for Integers |
106 | | */ |
107 | | class SymbolicIntVariable: public SymbolicVariable |
108 | | { |
109 | | public: |
110 | | SymbolicIntVariable( |
111 | | frontend::Type const* _type, |
112 | | frontend::Type const* _originalType, |
113 | | std::string _uniqueName, |
114 | | EncodingContext& _context |
115 | | ); |
116 | | }; |
117 | | |
118 | | /** |
119 | | * Specialization of SymbolicVariable for Address |
120 | | */ |
121 | | class SymbolicAddressVariable: public SymbolicIntVariable |
122 | | { |
123 | | public: |
124 | | SymbolicAddressVariable( |
125 | | std::string _uniqueName, |
126 | | EncodingContext& _context |
127 | | ); |
128 | | }; |
129 | | |
130 | | /** |
131 | | * Specialization of SymbolicVariable for FixedBytes |
132 | | */ |
133 | | class SymbolicFixedBytesVariable: public SymbolicIntVariable |
134 | | { |
135 | | public: |
136 | | SymbolicFixedBytesVariable( |
137 | | frontend::Type const* _originalType, |
138 | | unsigned _numBytes, |
139 | | std::string _uniqueName, |
140 | | EncodingContext& _context |
141 | | ); |
142 | | }; |
143 | | |
144 | | /** |
145 | | * Specialization of SymbolicVariable for FunctionType. |
146 | | * Besides containing a symbolic function declaration, |
147 | | * it also has an integer used as abstraction. |
148 | | * By default, the abstract representation is used when |
149 | | * values are requested, and the function declaration is |
150 | | * used when operator() is applied over arguments. |
151 | | */ |
152 | | class SymbolicFunctionVariable: public SymbolicVariable |
153 | | { |
154 | | public: |
155 | | SymbolicFunctionVariable( |
156 | | frontend::Type const* _type, |
157 | | std::string _uniqueName, |
158 | | EncodingContext& _context |
159 | | ); |
160 | | SymbolicFunctionVariable( |
161 | | smtutil::SortPointer _sort, |
162 | | std::string _uniqueName, |
163 | | EncodingContext& _context |
164 | | ); |
165 | | |
166 | | smtutil::Expression currentValue(frontend::Type const* _targetType = nullptr) const override; |
167 | | |
168 | | // Explicit request the function declaration. |
169 | | smtutil::Expression currentFunctionValue() const; |
170 | | |
171 | | smtutil::Expression valueAtIndex(unsigned _index) const override; |
172 | | |
173 | | // Explicit request the function declaration. |
174 | | smtutil::Expression functionValueAtIndex(unsigned _index) const; |
175 | | |
176 | | smtutil::Expression resetIndex() override; |
177 | | smtutil::Expression setIndex(unsigned _index) override; |
178 | | smtutil::Expression increaseIndex() override; |
179 | | |
180 | | smtutil::Expression operator()(std::vector<smtutil::Expression> const& _arguments) const override; |
181 | | |
182 | | private: |
183 | | /// Creates a new function declaration. |
184 | | void resetDeclaration(); |
185 | | |
186 | | /// Stores the current function declaration. |
187 | | smtutil::Expression m_declaration; |
188 | | |
189 | | /// Abstract representation. |
190 | | SymbolicIntVariable m_abstract{ |
191 | | TypeProvider::uint256(), |
192 | | TypeProvider::uint256(), |
193 | | m_uniqueName + "_abstract", |
194 | | m_context |
195 | | }; |
196 | | }; |
197 | | |
198 | | /** |
199 | | * Specialization of SymbolicVariable for Enum |
200 | | */ |
201 | | class SymbolicEnumVariable: public SymbolicVariable |
202 | | { |
203 | | public: |
204 | | SymbolicEnumVariable( |
205 | | frontend::Type const* _type, |
206 | | std::string _uniqueName, |
207 | | EncodingContext& _context |
208 | | ); |
209 | | }; |
210 | | |
211 | | /** |
212 | | * Specialization of SymbolicVariable for Tuple |
213 | | */ |
214 | | class SymbolicTupleVariable: public SymbolicVariable |
215 | | { |
216 | | public: |
217 | | SymbolicTupleVariable( |
218 | | frontend::Type const* _type, |
219 | | std::string _uniqueName, |
220 | | EncodingContext& _context |
221 | | ); |
222 | | SymbolicTupleVariable( |
223 | | smtutil::SortPointer _sort, |
224 | | std::string _uniqueName, |
225 | | EncodingContext& _context |
226 | | ); |
227 | | |
228 | | smtutil::Expression currentValue(frontend::Type const* _targetType = nullptr) const override; |
229 | | |
230 | | std::vector<smtutil::SortPointer> const& components() const; |
231 | | smtutil::Expression component( |
232 | | size_t _index, |
233 | | frontend::Type const* _fromType = nullptr, |
234 | | frontend::Type const* _toType = nullptr |
235 | | ) const; |
236 | | }; |
237 | | |
238 | | /** |
239 | | * Specialization of SymbolicVariable for Array |
240 | | */ |
241 | | class SymbolicArrayVariable: public SymbolicVariable |
242 | | { |
243 | | public: |
244 | | SymbolicArrayVariable( |
245 | | frontend::Type const* _type, |
246 | | frontend::Type const* _originalTtype, |
247 | | std::string _uniqueName, |
248 | | EncodingContext& _context |
249 | | ); |
250 | | SymbolicArrayVariable( |
251 | | smtutil::SortPointer _sort, |
252 | | std::string _uniqueName, |
253 | | EncodingContext& _context |
254 | | ); |
255 | | |
256 | | SymbolicArrayVariable(SymbolicArrayVariable&&) = default; |
257 | | |
258 | | smtutil::Expression currentValue(frontend::Type const* _targetType = nullptr) const override; |
259 | | smtutil::Expression valueAtIndex(unsigned _index) const override; |
260 | 76.6k | smtutil::Expression resetIndex() override { SymbolicVariable::resetIndex(); return m_pair.resetIndex(); } |
261 | 939 | smtutil::Expression setIndex(unsigned _index) override { SymbolicVariable::setIndex(_index); return m_pair.setIndex(_index); } |
262 | 176k | smtutil::Expression increaseIndex() override { SymbolicVariable::increaseIndex(); return m_pair.increaseIndex(); } |
263 | | smtutil::Expression elements() const; |
264 | | smtutil::Expression length() const; |
265 | | |
266 | 0 | smtutil::SortPointer tupleSort() { return m_pair.sort(); } |
267 | | |
268 | | private: |
269 | | SymbolicTupleVariable m_pair; |
270 | | }; |
271 | | |
272 | | /** |
273 | | * Specialization of SymbolicVariable for Struct. |
274 | | */ |
275 | | class SymbolicStructVariable: public SymbolicVariable |
276 | | { |
277 | | public: |
278 | | SymbolicStructVariable( |
279 | | frontend::Type const* _type, |
280 | | std::string _uniqueName, |
281 | | EncodingContext& _context |
282 | | ); |
283 | | |
284 | | /// @returns the symbolic expression representing _member. |
285 | | smtutil::Expression member(std::string const& _member) const; |
286 | | |
287 | | /// @returns the symbolic expression representing this struct |
288 | | /// with field _member updated. |
289 | | smtutil::Expression assignMember(std::string const& _member, smtutil::Expression const& _memberValue); |
290 | | |
291 | | /// @returns the symbolic expression representing this struct |
292 | | /// with all fields updated with the given values. |
293 | | smtutil::Expression assignAllMembers(std::vector<smtutil::Expression> const& _memberValues); |
294 | | |
295 | | private: |
296 | | std::map<std::string, unsigned> m_memberIndices; |
297 | | }; |
298 | | |
299 | | |
300 | | |
301 | | } |