Skip to content

fix(sema): reject void typed arguments to abi.encode#1889

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

fix(sema): reject void typed arguments to abi.encode#1889
aryanbaranwal001 wants to merge 1 commit intohyperledger-solang:mainfrom
aryanbaranwal001:fix/reject-void-abi-encode

Conversation

@aryanbaranwal001
Copy link
Copy Markdown

This PR fixes a compiler panic when a void returning expression 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::Void. So when a void returning expression like require(true) or a user defined void function g() is passed as an argument, sema accepts it without error and stores it in the AST as ast::Expression::Builtin { kind: Require, tys: [Type::Void], ... }.

codegen/expression.rs:1050, codegen's expression() matches ast::Builtin::AbiEncodePacked and calls abi_encode_packed() at codegen/expression.rs:1853.

abi_encode_packed then maps expression() over each arg. For Builtin::Require, this calls revert::require() at codegen/revert.rs:235, which emits the branch IR and returns Expression::Poison. That Poison is put into the packed args list.

abi_encode_packed passes the list to abi_encode() at codegen/expression.rs:1858.

abi_encode calls calculate_size_args() at codegen/encoding/mod.rs:48.

calculate_size_args calls get_expr_size() at codegen/encoding/mod.rs:176.

get_expr_size immediately calls expr.ty() on Expression::Poison, which hits Expression::Poison => unreachable!("Expression does not have a type") at codegen/mod.rs:1003 and panics.

Fix

Add a Type::Void guard in the arg resolution loop at sema/builtin.rs:1404, after the arg is resolved and before the is_mapping check:

if expr.tys().len() == 1 && expr.tys()[0] == Type::Void {
    diagnostics.push(Diagnostic::error(
        arg.loc(),
        "cannot pass a void expression as an abi.encode argument".to_string(),
    ));
    return Err(());
}

This makes sema reject void arguments before they reach codegen. The fix covers all affected variants, 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(require(true));
  • abi.encode(require(true));
  • abi.encodePacked(g()); where function g() public {}

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: Expression does not have a type when abi.encodePacked receives a void-returning call

1 participant