Coverage Report

Created: 2026-08-14 07:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/solidity/libsolidity/formal/EncodingContext.cpp
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
#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
59.5M
{
31
59.5M
  return lhs->id() < rhs->id();
32
59.5M
}
33
34
EncodingContext::EncodingContext():
35
15.7k
  m_state(*this)
36
15.7k
{
37
15.7k
}
38
39
void EncodingContext::reset()
40
68.6k
{
41
68.6k
  resetAllVariables();
42
68.6k
  m_expressions.clear();
43
68.6k
  m_globalContext.clear();
44
68.6k
  m_state.reset();
45
68.6k
  m_assertions.clear();
46
68.6k
}
47
48
void EncodingContext::resetUniqueId()
49
16.6k
{
50
16.6k
  m_nextUniqueId = 0;
51
16.6k
}
52
53
unsigned EncodingContext::newUniqueId()
54
58.4k
{
55
58.4k
  return m_nextUniqueId++;
56
58.4k
}
57
58
/// Variables.
59
60
std::shared_ptr<SymbolicVariable> EncodingContext::variable(frontend::VariableDeclaration const& _varDecl)
61
2.11M
{
62
2.11M
  solAssert(knownVariable(_varDecl), "");
63
2.11M
  return m_variables[&_varDecl];
64
2.11M
}
65
66
bool EncodingContext::createVariable(frontend::VariableDeclaration const& _varDecl)
67
29.8k
{
68
29.8k
  solAssert(!knownVariable(_varDecl), "");
69
29.8k
  auto const& type = _varDecl.type();
70
29.8k
  auto result = newSymbolicVariable(*type, _varDecl.name() + "_" + std::to_string(_varDecl.id()), *this);
71
29.8k
  m_variables.emplace(&_varDecl, result.second);
72
29.8k
  return result.first;
73
29.8k
}
74
75
bool EncodingContext::knownVariable(frontend::VariableDeclaration const& _varDecl)
76
3.22M
{
77
3.22M
  return m_variables.count(&_varDecl);
78
3.22M
}
79
80
void EncodingContext::resetVariable(frontend::VariableDeclaration const& _variable)
81
199k
{
82
199k
  newValue(_variable);
83
199k
  setUnknownValue(_variable);
84
199k
}
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
150k
{
94
150k
  for_each(begin(m_variables), end(m_variables), [&](auto _variable)
95
292k
  {
96
292k
    if (_filter(*_variable.first))
97
198k
      this->resetVariable(*_variable.first);
98
292k
  });
99
150k
}
100
101
void EncodingContext::resetAllVariables()
102
104k
{
103
180k
  resetVariables([&](frontend::VariableDeclaration const&) { return true; });
104
104k
}
105
106
smtutil::Expression EncodingContext::newValue(frontend::VariableDeclaration const& _decl)
107
211k
{
108
211k
  solAssert(knownVariable(_decl), "");
109
211k
  return m_variables.at(&_decl)->increaseIndex();
110
211k
}
111
112
void EncodingContext::setZeroValue(frontend::VariableDeclaration const& _decl)
113
41.0k
{
114
41.0k
  solAssert(knownVariable(_decl), "");
115
41.0k
  setZeroValue(*m_variables.at(&_decl));
116
41.0k
}
117
118
void EncodingContext::setZeroValue(SymbolicVariable& _variable)
119
41.1k
{
120
41.1k
  setSymbolicZeroValue(_variable, *this);
121
41.1k
}
122
123
void EncodingContext::setUnknownValue(frontend::VariableDeclaration const& _decl)
124
216k
{
125
216k
  solAssert(knownVariable(_decl), "");
126
216k
  setUnknownValue(*m_variables.at(&_decl));
127
216k
}
128
129
void EncodingContext::setUnknownValue(SymbolicVariable& _variable)
130
218k
{
131
218k
  setSymbolicUnknownValue(_variable, *this);
132
218k
}
133
134
/// Expressions
135
136
std::shared_ptr<SymbolicVariable> EncodingContext::expression(frontend::Expression const& _e)
137
1.15M
{
138
1.15M
  if (!knownExpression(_e))
139
618
    createExpression(_e);
140
1.15M
  return m_expressions.at(&_e);
141
1.15M
}
142
143
bool EncodingContext::createExpression(frontend::Expression const& _e, std::shared_ptr<SymbolicVariable> _symbVar)
144
537k
{
145
537k
  solAssert(_e.annotation().type, "");
146
537k
  if (knownExpression(_e))
147
170k
  {
148
170k
    expression(_e)->increaseIndex();
149
170k
    return false;
150
170k
  }
151
367k
  else if (_symbVar)
152
8.62k
  {
153
8.62k
    m_expressions.emplace(&_e, _symbVar);
154
8.62k
    return false;
155
8.62k
  }
156
358k
  else
157
358k
  {
158
358k
    auto result = newSymbolicVariable(*_e.annotation().type, "expr_" + std::to_string(_e.id()), *this);
159
358k
    m_expressions.emplace(&_e, result.second);
160
358k
    return result.first;
161
358k
  }
162
537k
}
163
164
bool EncodingContext::knownExpression(frontend::Expression const& _e) const
165
2.63M
{
166
2.63M
  return m_expressions.count(&_e);
167
2.63M
}
168
169
/// Global variables and functions.
170
171
std::shared_ptr<SymbolicVariable> EncodingContext::globalSymbol(std::string const& _name)
172
3.22k
{
173
3.22k
  solAssert(knownGlobalSymbol(_name), "");
174
3.22k
  return m_globalContext.at(_name);
175
3.22k
}
176
177
bool EncodingContext::createGlobalSymbol(std::string const& _name, frontend::Expression const& _expr)
178
1.79k
{
179
1.79k
  solAssert(!knownGlobalSymbol(_name), "");
180
1.79k
  auto result = newSymbolicVariable(*_expr.annotation().type, _name, *this);
181
1.79k
  m_globalContext.emplace(_name, result.second);
182
1.79k
  setUnknownValue(*result.second);
183
1.79k
  return result.first;
184
1.79k
}
185
186
bool EncodingContext::knownGlobalSymbol(std::string const& _var) const
187
8.13k
{
188
8.13k
  return m_globalContext.count(_var);
189
8.13k
}
190
191
/// Solver.
192
193
smtutil::Expression EncodingContext::assertions()
194
291k
{
195
291k
  if (m_assertions.empty())
196
51.4k
    return smtutil::Expression(true);
197
198
239k
  return m_assertions.back();
199
291k
}
200
201
void EncodingContext::pushSolver()
202
235k
{
203
235k
  if (m_accumulateAssertions)
204
37.1k
    m_assertions.push_back(assertions());
205
198k
  else
206
198k
    m_assertions.emplace_back(true);
207
235k
}
208
209
void EncodingContext::popSolver()
210
235k
{
211
235k
  solAssert(!m_assertions.empty(), "");
212
235k
  m_assertions.pop_back();
213
235k
}
214
215
void EncodingContext::addAssertion(smtutil::Expression const& _expr)
216
1.20M
{
217
1.20M
  if (m_assertions.empty())
218
40.0k
    m_assertions.push_back(_expr);
219
1.16M
  else
220
1.16M
    m_assertions.back() = _expr && std::move(m_assertions.back());
221
1.20M
}