Skip to content

Commit 556934e

Browse files
authored
Merge pull request #72 from onbloc/fix-zkgm-byte-slice-boundaries
fix(ibc): harden zkgm byte slice boundaries
2 parents 09b8ce7 + 79aa077 commit 556934e

2 files changed

Lines changed: 42 additions & 13 deletions

File tree

gno.land/r/core/ibc/v1/apps/zkgm/v0/impl/call.gno

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ func (v *ZkgmV1) executeCall(packet core.Packet, relayer address, relayerMsg []b
2929
return callErrAck(errEurekaUnsupported), nil
3030
}
3131

32-
receiverPath := string(call.ContractAddress)
32+
sender := cloneBytes(call.Sender)
33+
calldata := cloneBytes(call.ContractCalldata)
34+
receiverPath := string(cloneBytes(call.ContractAddress))
3335
receiver := zkgm.GetReceiver(receiverPath)
3436
if receiver == nil {
3537
return callErrAck(errors.New("zkgm/v1: receiver not registered: " + receiverPath)), nil
@@ -38,14 +40,14 @@ func (v *ZkgmV1) executeCall(packet core.Packet, relayer address, relayerMsg []b
3840
relayerStr := string(relayer)
3941
env := z.CallEnv{
4042
Caller: relayerStr,
41-
ProxyAccount: PredictCallProxyAccount(path, packet.DestinationChannelId, call.Sender),
43+
ProxyAccount: PredictCallProxyAccount(path, packet.DestinationChannelId, sender),
4244
Path: path,
4345
SourceChannel: packet.SourceChannelId.String(),
4446
DestinationChannel: packet.DestinationChannelId.String(),
45-
Sender: call.Sender,
46-
Calldata: call.ContractCalldata,
47+
Sender: sender,
48+
Calldata: calldata,
4749
Relayer: []byte(relayerStr),
48-
RelayerMsg: []byte(relayerMsg),
50+
RelayerMsg: cloneBytes(relayerMsg),
4951
}
5052

5153
err, panicked := safeCallOnZkgm(receiver, env)
@@ -77,11 +79,38 @@ func (v *ZkgmV1) timeoutCall(packet core.Packet, path *u256.Uint, call z.Call) e
7779
return nil
7880
}
7981

82+
// safeCallOnZkgm runs the receiver and reports a failure as panicked=true.
83+
// revive is preferred since it also catches cross-realm aborts; the recover
84+
// fallback, used only when revive is unsupported, catches ordinary panics.
8085
func safeCallOnZkgm(receiver z.Zkgmable, env z.CallEnv) (err error, panicked bool) {
81-
p := revive(func() {
82-
err = receiver.OnZkgm(cross, env)
83-
})
84-
return err, p != nil
86+
if canRevive() {
87+
p := revive(func() {
88+
err = receiver.OnZkgm(cross, env)
89+
})
90+
return err, p != nil
91+
}
92+
93+
defer func() {
94+
if recover() != nil {
95+
err = nil
96+
panicked = true
97+
}
98+
}()
99+
err = receiver.OnZkgm(cross, env)
100+
return err, false
101+
}
102+
103+
// canRevive reports whether revive works in the current runtime. revive panics
104+
// rather than returning when the interpreter lacks support for it.
105+
func canRevive() (ok bool) {
106+
ok = true
107+
defer func() {
108+
if recover() != nil {
109+
ok = false
110+
}
111+
}()
112+
revive(func() {})
113+
return ok
85114
}
86115

87116
func callErrAck(err error) core.RecvPacketResult {

gno.land/r/core/ibc/v1/apps/zkgm/v0/impl/impl.gno

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (v *ZkgmV1) PreChannelCloseInit(channelId core.ChannelId) {}
3333
func (v *ZkgmV1) PostChannelCloseConfirm(channelId core.ChannelId) {}
3434

3535
func (v *ZkgmV1) Recv(packet core.Packet, relayer address, relayerMsg []byte) core.RecvPacketResult {
36-
zp, err := z.DecodeZkgmPacket(packet.Data)
36+
zp, err := z.DecodeZkgmPacket(cloneBytes(packet.Data))
3737
if err != nil {
3838
return errResult(err)
3939
}
@@ -45,7 +45,7 @@ func (v *ZkgmV1) Recv(packet core.Packet, relayer address, relayerMsg []byte) co
4545
}
4646

4747
func (v *ZkgmV1) Ack(packet core.Packet, ack []byte, relayer address) {
48-
zp, err := z.DecodeZkgmPacket(packet.Data)
48+
zp, err := z.DecodeZkgmPacket(cloneBytes(packet.Data))
4949
if err != nil {
5050
panic(err.Error())
5151
}
@@ -59,7 +59,7 @@ func (v *ZkgmV1) Ack(packet core.Packet, ack []byte, relayer address) {
5959
}
6060

6161
func (v *ZkgmV1) Timeout(packet core.Packet, relayer address) {
62-
zp, err := z.DecodeZkgmPacket(packet.Data)
62+
zp, err := z.DecodeZkgmPacket(cloneBytes(packet.Data))
6363
if err != nil {
6464
panic(err.Error())
6565
}
@@ -78,7 +78,7 @@ func (v *ZkgmV1) Timeout(packet core.Packet, relayer address) {
7878
// outcome where appropriate. The result is dropped because the new
7979
// OnIntentRecvPacket callback has no return.
8080
func (v *ZkgmV1) IntentRecv(packet core.Packet, marketMaker address, marketMakerMsg []byte) {
81-
zp, err := z.DecodeZkgmPacket(packet.Data)
81+
zp, err := z.DecodeZkgmPacket(cloneBytes(packet.Data))
8282
if err != nil {
8383
panic(err.Error())
8484
}

0 commit comments

Comments
 (0)