Fixed fuzzing.

This commit is contained in:
treeform 2022-02-11 21:08:24 -08:00
parent 81b82e2277
commit d250e4be01
3 changed files with 19 additions and 18 deletions

View file

@ -35,8 +35,8 @@ proc decodeBmp*(data: string): Image {.raises: [PixieError].} =
useAlpha = false useAlpha = false
flipVertical = false flipVertical = false
if numColors < 0: if numColors < 0 or numColors > 256:
raise newException(PixieError, "Invalid BMP data") raise newException(PixieError, "Invalid number of colors")
if dibHeader notin [40, 108]: if dibHeader notin [40, 108]:
raise newException(PixieError, "Invalid BMP data") raise newException(PixieError, "Invalid BMP data")
@ -101,10 +101,10 @@ proc decodeBmp*(data: string): Image {.raises: [PixieError].} =
if padding > 0: if padding > 0:
offset += 4 - padding offset += 4 - padding
for x in 0 ..< result.width: for x in 0 ..< result.width:
if offset >= data.len:
raise newException(PixieError, "Truncated BMP data")
var rgba: ColorRGBA var rgba: ColorRGBA
if haveBits == 0: if haveBits == 0:
if offset >= data.len:
raise newException(PixieError, "Truncated BMP data")
colorBits = data.readUint8(offset) colorBits = data.readUint8(offset)
haveBits = 8 haveBits = 8
offset += 1 offset += 1
@ -127,10 +127,10 @@ proc decodeBmp*(data: string): Image {.raises: [PixieError].} =
if padding > 0: if padding > 0:
offset += 4 - padding offset += 4 - padding
for x in 0 ..< result.width: for x in 0 ..< result.width:
if offset >= data.len:
raise newException(PixieError, "Truncated BMP data")
var rgba: ColorRGBA var rgba: ColorRGBA
if haveBits == 0: if haveBits == 0:
if offset >= data.len:
raise newException(PixieError, "Truncated BMP data")
colorBits = data.readUint8(offset) colorBits = data.readUint8(offset)
haveBits = 8 haveBits = 8
offset += 1 offset += 1
@ -163,10 +163,10 @@ proc decodeBmp*(data: string): Image {.raises: [PixieError].} =
for y in 0 ..< result.height: for y in 0 ..< result.height:
# pad the row # pad the row
let padding = (offset - startOffset) mod 4 let padding = (offset - startOffset) mod 4
if padding >= 0: if padding > 0:
offset += 4 - padding offset += 4 - padding
for x in 0 ..< result.width: for x in 0 ..< result.width:
if offset + 3 > data.len: if offset + 2 >= data.len:
raise newException(PixieError, "Truncated BMP data") raise newException(PixieError, "Truncated BMP data")
var rgba: ColorRGBA var rgba: ColorRGBA
rgba.r = data.readUint8(offset + 2) rgba.r = data.readUint8(offset + 2)
@ -176,10 +176,10 @@ proc decodeBmp*(data: string): Image {.raises: [PixieError].} =
offset += 3 offset += 3
result[x, result.height - y - 1] = rgba.rgbx() result[x, result.height - y - 1] = rgba.rgbx()
if bits == 32: elif bits == 32:
for y in 0 ..< result.height: for y in 0 ..< result.height:
for x in 0 ..< result.width: for x in 0 ..< result.width:
if offset >= data.len - 2: if offset + 3 >= data.len:
raise newException(PixieError, "Truncated BMP data") raise newException(PixieError, "Truncated BMP data")
var rgba: ColorRGBA var rgba: ColorRGBA
let color = data.readUint32(offset) let color = data.readUint32(offset)

View file

@ -2,12 +2,13 @@ import pixie/common, pixie/fileformats/bmp, random, strformat, flatty/binny, os
randomize() randomize()
var originals = @[readFile("tests/fileformats/bmp/knight.32.bmp")] var originals = @["tests/fileformats/bmp/knight.32.bmp"]
for file in walkFiles("tests/fileformats/bmp/bmpsuite/*"): for file in walkFiles("tests/fileformats/bmp/bmpsuite/*"):
originals.add(readFile(file)) originals.add(file)
for i in 0 ..< 100_000: for i in 0 ..< 1000:
var data = originals[rand(originals.len-1)] let file = originals[rand(originals.len-1)]
var data = readFile(file)
let let
pos = rand(data.len-1) pos = rand(data.len-1)
value = rand(255).char value = rand(255).char
@ -18,12 +19,11 @@ for i in 0 ..< 100_000:
let let
width = data.readInt32(18).int width = data.readInt32(18).int
height = data.readInt32(22).int height = data.readInt32(22).int
numColors = data.readInt32(46).int if abs(width) > 1000 or abs(height) > 1000:
if abs(width) > 1000 or abs(height) > 1000 or numColors > 1000:
echo "too big" echo "too big"
continue continue
echo &"{i} {pos} {repr(value)}" echo &"{i} {file} {pos} {repr(value)}"
try: try:
let img = decodeBmp(data) let img = decodeBmp(data)
doAssert img.height > 0 and img.width > 0 doAssert img.height > 0 and img.width > 0

View file

@ -45,5 +45,6 @@ block:
block: block:
for file in walkFiles("tests/fileformats/bmp/bmpsuite/*"): for file in walkFiles("tests/fileformats/bmp/bmpsuite/*"):
# echo file
let image = decodeBmp(readFile(file)) let image = decodeBmp(readFile(file))
image.writeFile(file.replace("bmpsuite", "output") & ".png") #image.writeFile(file.replace("bmpsuite", "output") & ".png")