distlib/luigi/zookeeper/mybatis/solc/solana/go-ethereum: CWE-407 patches + unit tests; solana CLEAN
This commit is contained in:
parent
c9e86c450c
commit
b4e2eda927
17 changed files with 2087 additions and 1 deletions
45
defects/solc/patch/CLEAN-solc-0002.md
Normal file
45
defects/solc/patch/CLEAN-solc-0002.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# solc-0002 — ContractLevelChecker findDuplicateDefinitions — CLEAN (CWE-407)
|
||||
|
||||
## File
|
||||
`libsolidity/analysis/ContractLevelChecker.cpp` ~line 239
|
||||
|
||||
## Pattern reviewed
|
||||
```cpp
|
||||
std::set<size_t> reported;
|
||||
for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
|
||||
```
|
||||
|
||||
## CWE-407 verdict: NOT a performance defect
|
||||
|
||||
`std::set<size_t>::count` is O(log N), making the loop O(N log N) — well within
|
||||
acceptable complexity for the use case. N is bounded by the number of overloaded
|
||||
definitions of a single name in a contract, which in practice is tiny (< 20).
|
||||
No CWE-407 patch warranted.
|
||||
|
||||
## Separate logic concern (not CWE-407)
|
||||
|
||||
The `!reported.count(i)` loop guard has a latent correctness defect: if index `i`
|
||||
was inserted into `reported` as a *duplicate* during an earlier outer iteration
|
||||
(e.g., iteration i=0 found j=2 is a duplicate and inserted 2), then when the outer
|
||||
loop reaches i=2 the guard fires and the loop exits early. This causes i=2 to be
|
||||
silently skipped as a *primary* candidate, potentially missing further duplicates
|
||||
whose first occurrence is at index 2.
|
||||
|
||||
This is a correctness/logic defect, not a CWE-407 algorithmic-complexity defect.
|
||||
It should be tracked separately if it produces missed duplicate-definition errors
|
||||
in practice.
|
||||
|
||||
## Recommendation
|
||||
|
||||
Change the loop guard to allow all `i` to be visited as primary candidates:
|
||||
|
||||
```cpp
|
||||
for (size_t i = 0; i < overloads.size(); ++i)
|
||||
{
|
||||
if (reported.count(i)) continue; // already flagged as someone else's dup
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
This preserves the intent (skip reporting i if it was already reported as a
|
||||
duplicate of an earlier declaration) while not prematurely terminating the loop.
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
# UNDF: UNDF-2026-000000288
|
||||
--- a/libsolidity/analysis/TypeChecker.cpp
|
||||
+++ b/libsolidity/analysis/TypeChecker.cpp
|
||||
@@ -3611,9 +3611,17 @@ std::vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
|
||||
Identifier const& _identifier,
|
||||
std::vector<Declaration const*> const& _candidates
|
||||
)
|
||||
{
|
||||
solAssert(_candidates.size() > 1, "");
|
||||
+
|
||||
+ // CWE-407 fix: use a set keyed by canonical parameter-type string to avoid
|
||||
+ // the O(N²) find_if scan. For each incoming declaration we resolve its
|
||||
+ // FunctionType once, serialise the parameter+return types into a string key,
|
||||
+ // and do an O(1) unordered_set probe instead of a linear walk over
|
||||
+ // uniqueDeclarations. The original code called declaration->functionType()
|
||||
+ // twice (false then true) inside an inner lambda that was invoked once per
|
||||
+ // already-accumulated unique entry — O(N²) function-type resolutions in the
|
||||
+ // worst case where every declaration has a distinct signature.
|
||||
std::vector<Declaration const*> uniqueDeclarations;
|
||||
+ std::unordered_set<std::string> seenSignatures;
|
||||
|
||||
for (Declaration const* declaration: _candidates)
|
||||
{
|
||||
@@ -3631,15 +3639,17 @@ std::vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
|
||||
FunctionTypePointer functionType {declaration->functionType(false)};
|
||||
if (!functionType)
|
||||
functionType = declaration->functionType(true);
|
||||
solAssert(functionType, "Failed to determine the function type of the overloaded.");
|
||||
|
||||
for (Type const* parameter: functionType->parameterTypes() + functionType->returnParameterTypes())
|
||||
if (!parameter)
|
||||
m_errorReporter.fatalDeclarationError(3893_error, _identifier.location(), "Function type can not be used in this context.");
|
||||
|
||||
- if (uniqueDeclarations.end() == find_if(
|
||||
- uniqueDeclarations.begin(),
|
||||
- uniqueDeclarations.end(),
|
||||
- [&](Declaration const* d)
|
||||
- {
|
||||
- FunctionType const* newFunctionType = d->functionType(false);
|
||||
- if (!newFunctionType)
|
||||
- newFunctionType = d->functionType(true);
|
||||
- return newFunctionType && functionType->hasEqualParameterTypes(*newFunctionType);
|
||||
- }
|
||||
- ))
|
||||
+ // Build a canonical signature key from parameter and return types.
|
||||
+ // Two declarations are considered duplicates iff their parameter types
|
||||
+ // are equal (hasEqualParameterTypes), so we key on the human-readable
|
||||
+ // parameter-type string which FunctionType already exposes via
|
||||
+ // toString(false) on each parameter. This gives O(1) duplicate
|
||||
+ // detection instead of the prior O(N) find_if per candidate.
|
||||
+ std::string sigKey;
|
||||
+ for (Type const* p : functionType->parameterTypes())
|
||||
+ sigKey += p->toString(false) + ",";
|
||||
+ sigKey += "|";
|
||||
+ for (Type const* r : functionType->returnParameterTypes())
|
||||
+ sigKey += r->toString(false) + ",";
|
||||
+
|
||||
+ if (seenSignatures.insert(sigKey).second)
|
||||
uniqueDeclarations.push_back(declaration);
|
||||
}
|
||||
return uniqueDeclarations;
|
||||
Loading…
Add table
Add a link
Reference in a new issue