eth/protocols/eth: fix overflows in GetBlockHeader

This commit is contained in:
antonis19 2025-03-28 12:57:00 +01:00
parent 32f36a6749
commit fff62a2875
2 changed files with 44 additions and 5 deletions

View file

@ -297,6 +297,34 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
backend.chain.GetBlockByNumber(0).Hash(),
},
},
// Check a corner case where skipping causes overflow with reverse=false
{
&GetBlockHeadersRequest{Origin: HashOrNumber{Number: 1}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1},
[]common.Hash{
backend.chain.GetBlockByNumber(1).Hash(),
},
},
// Check a corner case where skipping causes overflow with reverse=false
{
&GetBlockHeadersRequest{Origin: HashOrNumber{Number: 1}, Amount: 2, Reverse: true, Skip: math.MaxUint64 - 1},
[]common.Hash{
backend.chain.GetBlockByNumber(1).Hash(),
},
},
// Check another corner case where skipping causes overflow with reverse=false
{
&GetBlockHeadersRequest{Origin: HashOrNumber{Number: 1}, Amount: 2, Reverse: false, Skip: math.MaxUint64},
[]common.Hash{
backend.chain.GetBlockByNumber(1).Hash(),
},
},
// Check another corner case where skipping causes overflow with reverse=false
{
&GetBlockHeadersRequest{Origin: HashOrNumber{Number: 1}, Amount: 2, Reverse: true, Skip: math.MaxUint64},
[]common.Hash{
backend.chain.GetBlockByNumber(1).Hash(),
},
},
// Check a corner case where skipping overflow loops back into the chain start
{
&GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1},

View file

@ -128,15 +128,26 @@ func serviceNonContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBloc
}
case query.Reverse:
// Number based traversal towards the genesis block
if query.Origin.Number >= query.Skip+1 {
query.Origin.Number -= query.Skip + 1
} else {
current := query.Origin.Number
ancestor := current - (query.Skip + 1)
if ancestor >= current { // check for underflow
infos, _ := json.MarshalIndent(peer.Peer.Info(), "", " ")
peer.Log().Warn("GetBlockHeaders skip underflow attack", "current", current, "skip", query.Skip, "ancestor", ancestor, "attacker", infos)
unknown = true
} else {
query.Origin.Number = ancestor
}
case !query.Reverse:
// Number based traversal towards the leaf block
query.Origin.Number += query.Skip + 1
current := query.Origin.Number
next := current + query.Skip + 1
if next <= current { // check for overflow
infos, _ := json.MarshalIndent(peer.Peer.Info(), "", " ")
peer.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos)
unknown = true
} else {
query.Origin.Number = next
}
}
}
return headers