mirror of
https://github.com/btcsuite/btcd.git
synced 2025-03-27 02:37:10 +01:00
Fix block boundary checking in FetchBlockRegion(s)
This commit is contained in:
parent
7d2daa5bfe
commit
d125e1fce4
3 changed files with 42 additions and 4 deletions
|
@ -56,6 +56,11 @@ const (
|
||||||
// [4:8] File offset (4 bytes)
|
// [4:8] File offset (4 bytes)
|
||||||
// [8:12] Block length (4 bytes)
|
// [8:12] Block length (4 bytes)
|
||||||
blockLocSize = 12
|
blockLocSize = 12
|
||||||
|
|
||||||
|
// blockMetadataSize is the number of bytes added as the metadata to
|
||||||
|
// a serialized block (4 bytes network version + 4 bytes block size +
|
||||||
|
// 4 bytes checksum).
|
||||||
|
blockMetadataSize = 12
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -1455,12 +1455,15 @@ func (tx *transaction) FetchBlockRegion(region *database.BlockRegion) ([]byte, e
|
||||||
}
|
}
|
||||||
location := deserializeBlockLoc(blockRow)
|
location := deserializeBlockLoc(blockRow)
|
||||||
|
|
||||||
|
// Calculate the actual block size by removing the metadata.
|
||||||
|
blockLen := location.blockLen - blockMetadataSize
|
||||||
|
|
||||||
// Ensure the region is within the bounds of the block.
|
// Ensure the region is within the bounds of the block.
|
||||||
endOffset := region.Offset + region.Len
|
endOffset := region.Offset + region.Len
|
||||||
if endOffset < region.Offset || endOffset > location.blockLen {
|
if endOffset < region.Offset || endOffset > blockLen {
|
||||||
str := fmt.Sprintf("block %s region offset %d, length %d "+
|
str := fmt.Sprintf("block %s region offset %d, length %d "+
|
||||||
"exceeds block length of %d", region.Hash,
|
"exceeds block length of %d", region.Hash,
|
||||||
region.Offset, region.Len, location.blockLen)
|
region.Offset, region.Len, blockLen)
|
||||||
return nil, makeDbErr(database.ErrBlockRegionInvalid, str, nil)
|
return nil, makeDbErr(database.ErrBlockRegionInvalid, str, nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1553,12 +1556,15 @@ func (tx *transaction) FetchBlockRegions(regions []database.BlockRegion) ([][]by
|
||||||
}
|
}
|
||||||
location := deserializeBlockLoc(blockRow)
|
location := deserializeBlockLoc(blockRow)
|
||||||
|
|
||||||
|
// Calculate the actual block size by removing the metadata.
|
||||||
|
blockLen := location.blockLen - blockMetadataSize
|
||||||
|
|
||||||
// Ensure the region is within the bounds of the block.
|
// Ensure the region is within the bounds of the block.
|
||||||
endOffset := region.Offset + region.Len
|
endOffset := region.Offset + region.Len
|
||||||
if endOffset < region.Offset || endOffset > location.blockLen {
|
if endOffset < region.Offset || endOffset > blockLen {
|
||||||
str := fmt.Sprintf("block %s region offset %d, length "+
|
str := fmt.Sprintf("block %s region offset %d, length "+
|
||||||
"%d exceeds block length of %d", region.Hash,
|
"%d exceeds block length of %d", region.Hash,
|
||||||
region.Offset, region.Len, location.blockLen)
|
region.Offset, region.Len, blockLen)
|
||||||
return nil, makeDbErr(database.ErrBlockRegionInvalid, str, nil)
|
return nil, makeDbErr(database.ErrBlockRegionInvalid, str, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1360,6 +1360,19 @@ func testFetchBlockIO(tc *testContext, tx database.Tx) bool {
|
||||||
if !checkDbError(tc.t, testName, err, wantErrCode) {
|
if !checkDbError(tc.t, testName, err, wantErrCode) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure fetching a block region larger than the block returns
|
||||||
|
// the expected error.
|
||||||
|
testName = fmt.Sprintf("FetchBlockRegion(%s) out of block size",
|
||||||
|
blockHash)
|
||||||
|
wantErrCode = database.ErrBlockRegionInvalid
|
||||||
|
region.Hash = blockHash
|
||||||
|
region.Offset = 0
|
||||||
|
region.Len = uint32(len(blockBytes) + 1)
|
||||||
|
_, err = tx.FetchBlockRegion(®ion)
|
||||||
|
if !checkDbError(tc.t, testName, err, wantErrCode) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------
|
// -----------------
|
||||||
|
@ -1500,6 +1513,20 @@ func testFetchBlockIO(tc *testContext, tx database.Tx) bool {
|
||||||
}
|
}
|
||||||
wantErrCode = database.ErrBlockRegionInvalid
|
wantErrCode = database.ErrBlockRegionInvalid
|
||||||
_, err = tx.FetchBlockRegions(badBlockRegions)
|
_, err = tx.FetchBlockRegions(badBlockRegions)
|
||||||
|
if !checkDbError(tc.t, testName, err, wantErrCode) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure fetching block regions larger than the block returns the
|
||||||
|
// expected error.
|
||||||
|
testName = "FetchBlockRegions out of bunds"
|
||||||
|
badBlockRegions = badBlockRegions[:len(badBlockRegions)-1]
|
||||||
|
for i := range badBlockRegions {
|
||||||
|
badBlockRegions[i].Offset = 0
|
||||||
|
badBlockRegions[i].Len = uint32(len(allBlockBytes[i]) + 1)
|
||||||
|
}
|
||||||
|
wantErrCode = database.ErrBlockRegionInvalid
|
||||||
|
_, err = tx.FetchBlockRegions(badBlockRegions)
|
||||||
return checkDbError(tc.t, testName, err, wantErrCode)
|
return checkDbError(tc.t, testName, err, wantErrCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue