Coverage Report

Created: 2026-07-13 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
55.2M
{
31
55.2M
  return lhs->id() < rhs->id();
32
55.2M
}
33
34
EncodingContext::EncodingContext():
35
14.6k
  m_state(*this)
36
14.6k
{
37
14.6k
}
38
39
void EncodingContext::reset()
40
63.8k
{
41
63.8k
  resetAllVariables();
42
63.8k
  m_expressions.clear();
43
63.8k
  m_globalContext.clear();
44
63.8k
  m_state.reset();
45
63.8k
  m_assertions.clear();
46
63.8k
}
47
48
void EncodingContext::resetUniqueId()
49
15.5k
{
50
15.5k
  m_nextUniqueId = 0;
51
15.5k
}
52
53
unsigned EncodingContext::newUniqueId()
54
55.5k
{
55
55.5k
  return m_nextUniqueId++;
56
55.5k
}
57
58
/// Variables.
59
60
std::shared_ptr<SymbolicVariable> EncodingContext::variable(frontend::VariableDeclaration const& _varDecl)
61
1.97M
{
62
1.97M
  solAssert(knownVariable(_varDecl), "");
63
1.97M
  return m_variables[&_varDecl];
64
1.97M
}
65
66
bool EncodingContext::createVariable(frontend::VariableDeclaration const& _varDecl)
67
28.3k
{
68
28.3k
  solAssert(!knownVariable(_varDecl), "");
69
28.3k
  auto const& type = _varDecl.type();
70
28.3k
  auto result = newSymbolicVariable(*type, _varDecl.name() + "_" + std::to_string(_varDecl.id()), *this);
71
28.3k
  m_variables.emplace(&_varDecl, result.second);
72
28.3k
  return result.first;
73
28.3k
}
74
75
bool EncodingContext::knownVariable(frontend::VariableDeclaration const& _varDecl)
76
3.01M
{
77
3.01M
  return m_variables.count(&_varDecl);
78
3.01M
}
79
80
void EncodingContext::resetVariable(frontend::VariableDeclaration const& _variable)
81
187k
{
82
187k
  newValue(_variable);
83
187k
  setUnknownValue(_variable);
84
187k
}
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
138k
{
94
138k
  for_each(begin(m_variables), end(m_variables), [&](auto _variable)
95
275k
  {
96
275k
    if (_filter(*_variable.first))
97
187k
      this->resetVariable(*_variable.first);
98
275k
  });
99
138k
}
100
101
void EncodingContext::resetAllVariables()
102
96.6k
{
103
171k
  resetVariables([&](frontend::VariableDeclaration const&) { return true; });
104
96.6k
}
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.0k
{
114
39.0k
  solAssert(knownVariable(_decl), "");
115
39.0k
  setZeroValue(*m_variables.at(&_decl));
116
39.0k
}
117
118
void EncodingContext::setZeroValue(SymbolicVariable& _variable)
119
39.1k
{
120
39.1k
  setSymbolicZeroValue(_variable, *this);
121
39.1k
}
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
206k
{
131
206k
  setSymbolicUnknownValue(_variable, *this);
132
206k
}
133
134
/// Expressions
135
136
std::shared_ptr<SymbolicVariable> EncodingContext::expression(frontend::Expression const& _e)
137
1.07M
{
138
1.07M
  if (!knownExpression(_e))
139
614
    createExpression(_e);
140
1.07M
  return m_expressions.at(&_e);
141
1.07M
}
142
143
bool EncodingContext::createExpression(frontend::Expression const& _e, std::shared_ptr<SymbolicVariable> _symbVar)
144
497k
{
145
497k
  solAssert(_e.annotation().type, "");
146
497k
  if (knownExpression(_e))
147
158k
  {
148
158k
    expression(_e)->increaseIndex();
149
158k
    return false;
150
158k
  }
151
339k
  else if (_symbVar)
152
8.17k
  {
153
8.17k
    m_expressions.emplace(&_e, _symbVar);
154
8.17k
    return false;
155
8.17k
  }
156
330k
  else
157
330k
  {
158
330k
    auto result = newSymbolicVariable(*_e.annotation().type, "expr_" + std::to_string(_e.id()), *this);
159
330k
    m_expressions.emplace(&_e, result.second);
160
330k
    return result.first;
161
330k
  }
162
497k
}
163
164
bool EncodingContext::knownExpression(frontend::Expression const& _e) const
165
2.43M
{
166
2.43M
  return m_expressions.count(&_e);
167
2.43M
}
168
169
/// Global variables and functions.
170
171
std::shared_ptr<SymbolicVariable> EncodingContext::globalSymbol(std::string const& _name)
172
3.09k
{
173
3.09k
  solAssert(knownGlobalSymbol(_name), "");
174
3.09k
  return m_globalContext.at(_name);
175
3.09k
}
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.82k
{
188
7.82k
  return m_globalContext.count(_var);
189
7.82k
}
190
191
/// Solver.
192
193
smtutil::Expression EncodingContext::assertions()
194
273k
{
195
273k
  if (m_assertions.empty())
196
48.5k
    return smtutil::Expression(true);
197
198
225k
  return m_assertions.back();
199
273k
}
200
201
void EncodingContext::pushSolver()
202
220k
{
203
220k
  if (m_accumulateAssertions)
204
34.5k
    m_assertions.push_back(assertions());
205
186k
  else
206
186k
    m_assertions.emplace_back(true);
207
220k
}
208
209
void EncodingContext::popSolver()
210
220k
{
211
220k
  solAssert(!m_assertions.empty(), "");
212
220k
  m_assertions.pop_back();
213
220k
}
214
215
void EncodingContext::addAssertion(smtutil::Expression const& _expr)
216
1.12M
{
217
1.12M
  if (m_assertions.empty())
218
37.4k
    m_assertions.push_back(_expr);
219
1.08M
  else
220
1.08M
    m_assertions.back() = _expr && std::move(m_assertions.back());
221
1.12M
}