argotorg / argotorg/solidity

`super` resolution ignores visibility and can select an `external` function

Open
#16,942 0 comments 0 reactions 1 assignee Claimed by @msooseth View on GitHub
bug :bug:
Dominant language
C++
Stars
25.7k
Forks
6.2k
Avg merge
2d 19h
Merged PRs (30d)
29

Description

Reported to us confidentially by [@cyberthirst](https://github.com/cyberthirst). We
analysed it and determined it is not a security issue, so we are filing it publicly
here as an ordinary compiler bug. Thanks to @cyberthirst for finding and reporting it.

A `super.f()` call is type-checked against the candidate set of the contract that
lexically contains it, but resolved again at code generation time over the
linearization of the most derived contract. `FunctionDefinition::resolveVirtual()`
matches candidates on name and parameter types only, it does not check
`isVisibleInDerivedContracts()`, so an `external` function is an eligible target.
But `super` is an internal call and can never legitimately reach an `external` function
body.

Currently:
- **legacy codegen** incorrectly emits an internal `JUMP` into the `external`
function's body. Miscompile.
- **via-IR** hits an assertion failure. Which is better, but not nice.

## Reproducer

`poc.sol`:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract A {
function f() public virtual returns (uint256) { return 1; }
}

contract X {
function f() external virtual returns (uint256) { return 100; }
}

contract B is A {
function f() public virtual override returns (uint256) { return super.f(); }
}

// C3 linearization of D: [D, B, X, A]
contract D is A, X, B {
function f() public override(A, X, B) returns (uint256) { return super.f(); }
}
```

## Expected behaviour

Should be a compile error,m with nice warning to user.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.