Coverage Report

Created: 2026-06-30 07:08

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