Skip to content

fix(sema): reject internal function references in abi.encode* arguments#1891

Open
aryanbaranwal001 wants to merge 1 commit intohyperledger-solang:mainfrom
aryanbaranwal001:fix/abi-encode-reject-internal-fn
Open

fix(sema): reject internal function references in abi.encode* arguments#1891
aryanbaranwal001 wants to merge 1 commit intohyperledger-solang:mainfrom
aryanbaranwal001:fix/abi-encode-reject-internal-fn

Conversation

@aryanbaranwal001
Copy link
Copy Markdown

This PR fixes a compiler panic when an internal function reference is passed as an argument to abi.encode*.

The root cause is that sema's abi.encode* argument resolution loop at sema/builtin.rs:1403 only guards against mapping and recursive types. It has no guard for Type::InternalFunction. So when a bare internal function reference like f is passed as an argument, sema accepts it without error and stores it in the AST with Type::InternalFunction and put into the args of ast::Expression::Builtin.

codegen/expression.rs:1048 matches ast::Builtin::AbiEncodePacked and calls abi_encode_packed() at codegen/expression.rs:1853.

abi_encode_packed maps expression() over each arg and passes the result to abi_encode() at codegen/expression.rs:1858.

abi_encode calls calculate_size_args() at codegen/encoding/mod.rs:48, which calls get_expr_size() at codegen/encoding/mod.rs:176.

get_expr_size matches on the expression's type. Type::InternalFunction hits the unreachable arm at codegen/encoding/mod.rs:1448–1453:

Type::InternalFunction { .. } | Type::Void | ... => unreachable!("This type cannot be encoded"),

Fix

Add a Type::InternalFunction guard in the arg resolution loop at sema/builtin.rs:1407, that is, immediately after the existing mapping/recursive check:

if matches!(ty, Type::InternalFunction { .. }) {
    diagnostics.push(Diagnostic::error(
        arg.loc(),
        "internal function references cannot be abi encoded".to_string(),
    ));
    return Err(());
}

This makes sema reject internal function references before they reach codegen. The fix covers abi.encode* variants such as abi.encode, abi.encodePacked, abi.encodeWithSelector, and abi.encodeWithSignature, since they all share the same loop at sema/builtin.rs:1403.

Previously panicking inputs:

  • abi.encodePacked(f);
  • abi.encode(f);

where f is a function in the same contract

Reproduces on polkadot, solana, and evm targets.

Signed-off-by: Aryan Baranwal <aryanbaranwal131214@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compiler panic in codegen: unreachable!("This type cannot be encoded") when abi-encoding an internal function reference

1 participant