hyperledger/solang

Accessing function selectors adds foreign contracts functions

xermicus opened this issue · 3 comments

If a contract function accesses the selector of another contracts function like so:

contract C {
    function ext_func_call(uint128 amount) public payable {
        A a = new A();
        (bool ok, bytes b) = address(a).call(
            bytes4(A.a.selector) // Here
        );
    }
}

contract A {
    function a() public pure {}
}

This will add function A::a to contract C. The dispatcher dispatches it and it's present in the metadata, which means it gets erroneously added and treated as a contract function further up the compilation pipeline.

I can reproduce this back to Solang v0.2.0; earlier versions segfault in emit so it's unclear when this regression was introduced (not recently).

I can reproduce it for Solana too:

/home/cyrill/Downloads/solang-linux-x86-64 --version
solang version v0.2.0

/home/cyrill/Downloads/solang-linux-x86-64 compile --target bug.sol --emit cfg

# function dispatch_C public:false selector: nonpayable:false
# params: buffer_pointer,uint64
# returns: 
block0: # entry
	branchcond ((arg #1) >= uint64 4), block1, block2
block1: # switch
	switch (builtin ReadFromBuffer ((arg #0), uint32 0)):
		case uint32 2051782505: goto block #3
		case uint32 3369171261: goto block #8
		case uint32 526892557: goto block #11
		default: goto block #2

526892557 is the selector of A::a.

Yes, you're right. That's not great. 😬

Fixed by #1462