native: fix oracle.finish reentrancy bug

See neo-project/neo#2795.
This commit is contained in:
Roman Khimov 2022-07-22 12:35:03 +03:00
parent 8d170a1eb8
commit bc3bffea53
2 changed files with 7 additions and 1 deletions

View file

@ -156,7 +156,7 @@ func TestOracle_Request(t *testing.T) {
putOracleRequest(t, helperValidatorInvoker, "url", nil, "handleRecursive", []byte{}, gasForResponse)
tx := prepareResponseTx(t, 2)
e.AddNewBlock(t, tx)
// e.CheckFault(t, tx.Hash(), "")
e.CheckFault(t, tx.Hash(), "Oracle.finish called from non-entry script")
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
require.NoError(t, err)
require.Equal(t, 2, len(aer[0].Events)) // OracleResponse + Invocation

View file

@ -276,6 +276,12 @@ func (o *Oracle) finish(ic *interop.Context, _ []stackitem.Item) stackitem.Item
// FinishInternal processes an oracle response.
func (o *Oracle) FinishInternal(ic *interop.Context) error {
if ic.VM.Istack().Len() != 2 {
return errors.New("Oracle.finish called from non-entry script")
}
if ic.Invocations[o.Hash] != 1 {
return errors.New("Oracle.finish called multiple times")
}
resp := getResponse(ic.Tx)
if resp == nil {
return ErrResponseNotFound