Coverage Report

Created: 2026-06-30 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}