Coverage Report

Created: 2025-06-24 07:59

/src/solidity/libsolidity/formal/EncodingContext.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/EncodingContext.h>
20
21
#include <libsolidity/ast/AST.h>
22
23
#include <libsolidity/formal/SymbolicTypes.h>
24
25
using namespace solidity;
26
using namespace solidity::util;
27
using namespace solidity::frontend::smt;
28
29
bool EncodingContext::IdCompare::operator()(ASTNode const* lhs, ASTNode const* rhs) const
30
57.5M
{
31
57.5M
  return lhs->id() < rhs->id();
32
57.5M
}
33
34
EncodingContext::EncodingContext():
35
  m_state(*this)
36
14.6k
{
37
14.6k
}
38
39
void EncodingContext::reset()
40
63.7k
{
41
63.7k
  resetAllVariables();
42
63.7k
  m_expressions.clear();
43
63.7k
  m_globalContext.clear();
44
63.7k
  m_state.reset();
45
63.7k
  m_assertions.clear();
46
63.7k
}
47
48
void EncodingContext::resetUniqueId()
49
15.5k
{
50
15.5k
  m_nextUniqueId = 0;
51
15.5k
}
52
53
unsigned EncodingContext::newUniqueId()
54
61.0k
{
55
61.0k
  return m_nextUniqueId++;
56
61.0k
}
57
58
/// Variables.
59
60
std::shared_ptr<SymbolicVariable> EncodingContext::variable(frontend::VariableDeclaration const& _varDecl)
61
1.96M
{
62
1.96M
  solAssert(knownVariable(_varDecl), "");
63
1.96M
  return m_variables[&_varDecl];
64
1.96M
}
65
66
bool EncodingContext::createVariable(frontend::VariableDeclaration const& _varDecl)
67
28.6k
{
68
28.6k
  solAssert(!knownVariable(_varDecl), "");
69
28.6k
  auto const& type = _varDecl.type();
70
28.6k
  auto result = newSymbolicVariable(*type, _varDecl.name() + "_" + std::to_string(_varDecl.id()), *this);
71
28.6k
  m_variables.emplace(&_varDecl, result.second);
72
28.6k
  return result.first;
73
28.6k
}
74
75
bool EncodingContext::knownVariable(frontend::VariableDeclaration const& _varDecl)
76
3.00M
{
77
3.00M
  return m_variables.count(&_varDecl);
78
3.00M
}
79
80
void EncodingContext::resetVariable(frontend::VariableDeclaration const& _variable)
81
188k
{
82
188k
  newValue(_variable);
83
188k
  setUnknownValue(_variable);
84
188k
}
85
86
void EncodingContext::resetVariables(std::set<frontend::VariableDeclaration const*> const& _variables)
87
0
{
88
0
  for (auto const* decl: _variables)
89
0
    resetVariable(*decl);
90
0
}
91
92
void EncodingContext::resetVariables(std::function<bool(frontend::VariableDeclaration const&)> const& _filter)
93
137k
{
94
137k
  for_each(begin(m_variables), end(m_variables), [&](auto _variable)
95
276k
  {
96
276k
    if (_filter(*_variable.first))
97
187k
      this->resetVariable(*_variable.first);
98
276k
  });
99
137k
}
100
101
void EncodingContext::resetAllVariables()
102
96.3k
{
103
172k
  resetVariables([&](frontend::VariableDeclaration const&) { return true; });
104
96.3k
}
105
106
smtutil::Expression EncodingContext::newValue(frontend::VariableDeclaration const& _decl)
107
199k
{
108
199k
  solAssert(knownVariable(_decl), "");
109
199k
  return m_variables.at(&_decl)->increaseIndex();
110
199k
}
111
112
void EncodingContext::setZeroValue(frontend::VariableDeclaration const& _decl)
113
39.7k
{
114
39.7k
  solAssert(knownVariable(_decl), "");
115
39.7k
  setZeroValue(*m_variables.at(&_decl));
116
39.7k
}
117
118
void EncodingContext::setZeroValue(SymbolicVariable& _variable)
119
39.7k
{
120
39.7k
  setSymbolicZeroValue(_variable, *this);
121
39.7k
}
122
123
void EncodingContext::setUnknownValue(frontend::VariableDeclaration const& _decl)
124
205k
{
125
205k
  solAssert(knownVariable(_decl), "");
126
205k
  setUnknownValue(*m_variables.at(&_decl));
127
205k
}
128
129
void EncodingContext::setUnknownValue(SymbolicVariable& _variable)
130
207k
{
131
207k
  setSymbolicUnknownValue(_variable, *this);
132
207k
}
133
134
/// Expressions
135
136
std::shared_ptr<SymbolicVariable> EncodingContext::expression(frontend::Expression const& _e)
137
1.11M
{
138
1.11M
  if (!knownExpression(_e))
139
633
    createExpression(_e);
140
1.11M
  return m_expressions.at(&_e);
141
1.11M
}
142
143
bool EncodingContext::createExpression(frontend::Expression const& _e, std::shared_ptr<SymbolicVariable> _symbVar)
144
513k
{
145
513k
  solAssert(_e.annotation().type, "");
146
513k
  if (knownExpression(_e))
147
163k
  {
148
163k
    expression(_e)->increaseIndex();
149
163k
    return false;
150
163k
  }
151
349k
  else if (_symbVar)
152
7.68k
  {
153
7.68k
    m_expressions.emplace(&_e, _symbVar);
154
7.68k
    return false;
155
7.68k
  }
156
342k
  else
157
342k
  {
158
342k
    auto result = newSymbolicVariable(*_e.annotation().type, "expr_" + std::to_string(_e.id()), *this);
159
342k
    m_expressions.emplace(&_e, result.second);
160
342k
    return result.first;
161
342k
  }
162
513k
}
163
164
bool EncodingContext::knownExpression(frontend::Expression const& _e) const
165
2.51M
{
166
2.51M
  return m_expressions.count(&_e);
167
2.51M
}
168
169
/// Global variables and functions.
170
171
std::shared_ptr<SymbolicVariable> EncodingContext::globalSymbol(std::string const& _name)
172
3.11k
{
173
3.11k
  solAssert(knownGlobalSymbol(_name), "");
174
3.11k
  return m_globalContext.at(_name);
175
3.11k
}
176
177
bool EncodingContext::createGlobalSymbol(std::string const& _name, frontend::Expression const& _expr)
178
1.74k
{
179
1.74k
  solAssert(!knownGlobalSymbol(_name), "");
180
1.74k
  auto result = newSymbolicVariable(*_expr.annotation().type, _name, *this);
181
1.74k
  m_globalContext.emplace(_name, result.second);
182
1.74k
  setUnknownValue(*result.second);
183
1.74k
  return result.first;
184
1.74k
}
185
186
bool EncodingContext::knownGlobalSymbol(std::string const& _var) const
187
7.86k
{
188
7.86k
  return m_globalContext.count(_var);
189
7.86k
}
190
191
/// Solver.
192
193
smtutil::Expression EncodingContext::assertions()
194
276k
{
195
276k
  if (m_assertions.empty())
196
51.3k
    return smtutil::Expression(true);
197
198
225k
  return m_assertions.back();
199
276k
}
200
201
void EncodingContext::pushSolver()
202
219k
{
203
219k
  if (m_accumulateAssertions)
204
34.1k
    m_assertions.push_back(assertions());
205
184k
  else
206
184k
    m_assertions.emplace_back(true);
207
219k
}
208
209
void EncodingContext::popSolver()
210
219k
{
211
219k
  solAssert(!m_assertions.empty(), "");
212
219k
  m_assertions.pop_back();
213
219k
}
214
215
void EncodingContext::addAssertion(smtutil::Expression const& _expr)
216
1.14M
{
217
1.14M
  if (m_assertions.empty())
218
37.8k
    m_assertions.push_back(_expr);
219
1.10M
  else
220
1.10M
    m_assertions.back() = _expr && std::move(m_assertions.back());
221
1.14M
}