Skip to content

Infinite recursion in RationalNumberType::isExplicitlyConvertibleTo when comparing m_value == 0 #16192

@yuucyf

Description

@yuucyf

Description

When debugging the Solidity compiler source code, I encountered an infinite recursion issue that causes a stack overflow.

Inside the function:

BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
	if (isImplicitlyConvertibleTo(_convertTo))
		return true;

	auto category = _convertTo.category();
	if (category == Category::FixedBytes)
		return false;
	else if (auto addressType = dynamic_cast<AddressType const*>(&_convertTo))
		return (m_value == 0) ||
			((addressType->stateMutability() != StateMutability::Payable) &&
			!isNegative() &&
			!isFractional() &&
			integerType() &&
			(integerType()->numBits() <= 160));
	else if (category == Category::Integer)
		return false;
	else if (auto enumType = dynamic_cast<EnumType const*>(&_convertTo))
		if (isNegative() || isFractional() || m_value >= enumType->numberOfMembers())
			return false;

	Type const* mobType = mobileType();
	return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo));
}

the statement:

return (m_value == 0);

leads to infinite recursion.
This happens because it matches the global overloaded operator:

template <class Arg, class IntType>
BOOST_CONSTEXPR
inline typename boost::enable_if_c<
    rational_detail::is_compatible_integer<Arg, IntType>::value,
    bool
>::type
operator==(const Arg& b, const rational<IntType>& a)
{
    return a == b;
}

I am using Boost 1.74.0.

solidity test code

function _transfer(address from, address to, uint256 value) internal {
    if (from == address(0)) {
        revert ERC20InvalidSender(address(0));
    }
    if (to == address(0)) {
        revert ERC20InvalidReceiver(address(0));
    }
    _update(from, to, value);
}

Expected behavior

The comparison m_value == 0 should evaluate correctly without triggering infinite recursion.

Actual behavior

The comparison triggers the global operator overload, which calls a == b again, leading to infinite recursion and eventually a stack overflow.

Environment

  • Compiler version: 0.8.30
  • Compilation pipeline:
  • Target EVM version (as per compiler settings):
  • Framework/IDE (e.g. Foundry, Hardhat, Remix):
  • Operating system: Ubuntu 22.04.1 LTS, GCC 11.4.0, Boost 1.74.0

Steps to Reproduce

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions