#16942·solidity

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

Author: msoosethCreated Aug 25, 2026Updated Sep 10, 2026
Labelsbug :bug:

Reported to us confidentially by @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.