1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from argparse import ArgumentParser
from pathlib import Path
from struct import calcsize, unpack
WR_IMAGEFORMATS = {
1: "R8",
2: "R16",
3: "BGRA8",
4: "RGBAF32",
5: "RG8",
6: "RG16",
7: "RGBAI32",
8: "RGBA8",
}
def bytes_to_hex_literal(data):
# data is bytes
# yields hex formatted strings like "0xFF"
# this can be simplified in 3.8+ using bytes.hex(sep=",").split(",")
hexified = iter(data.hex().upper())
# see grouper in itertools recipes
for result in zip(hexified, hexified):
yield f"0x{''.join(result)}"
def unpack_fp(fmt, fp):
# fmt is a struct format string
# fp is an open file handle
# returns tuple as per struct.unpack(fmt, ...)
size = calcsize(fmt)
return unpack(fmt, fp.read(size))
def main():
aparse = ArgumentParser()
aparse.add_argument("dump", type=Path, help="A Moz2D libFuzzer testcase to read")
args = aparse.parse_args()
with args.dump.open("rb") as dump:
(
aFormat, # B
aRenderRect_min_x, # 8i
aRenderRect_min_y,
aRenderRect_max_x,
aRenderRect_max_y,
aVisibleRect_min_x,
aVisibleRect_min_y,
aVisibleRect_max_x,
aVisibleRect_max_y,
aTileSize, # H
) = unpack_fp("=B8iH", dump)
if aTileSize:
(aTileOffset_x, aTileOffset_y) = unpack_fp("=2i", dump)
(aDirtyRect_notnull,) = unpack_fp("=B", dump)
if aDirtyRect_notnull:
(
aDirtyRect_min_x,
aDirtyRect_min_y,
aDirtyRect_max_x,
aDirtyRect_max_y,
) = unpack_fp("=4i", dump)
(output_len,) = unpack_fp("=I", dump)
blob_len = 0
print("const uint8_t blob_buffer[] = {")
while True:
line = tuple(bytes_to_hex_literal(dump.read(16)))
if not line:
break
blob_len += len(line)
print(f" {', '.join(line)},")
print("};")
print(f"uint8_t output_buffer[{output_len}];")
print("auto aRenderRect = mozilla::wr::LayoutIntRect {")
print(f" .min: {{ .x: {aRenderRect_min_x}, .y: {aRenderRect_min_y} }},")
print(f" .max: {{ .x: {aRenderRect_max_x}, .y: {aRenderRect_max_y} }},")
print("};")
print("auto aVisibleRect = mozilla::wr::DeviceIntRect {")
print(f" .min: {{ .x: {aVisibleRect_min_x}, .y: {aVisibleRect_min_y} }},")
print(f" .max: {{ .x: {aVisibleRect_max_x}, .y: {aVisibleRect_max_y} }},")
print("};")
if aTileSize:
print(f"uint16_t tileSize = {aTileSize};")
print("auto aTileOffset = mozilla::wr::TileOffset {")
print(f" .x: {aTileOffset_x}, .y: {aTileOffset_y},")
print("};")
aTileSize = "tileSize"
aTileOffset = "&aTileOffset"
else:
aTileSize = "0"
aTileOffset = "nullptr"
if aDirtyRect_notnull:
print("auto aDirtyRect = mozilla::wr::LayoutIntRect {")
print(f" .min: {{ .x: {aDirtyRect_min_x}, .y: {aDirtyRect_min_y} }},")
print(f" .max: {{ .x: {aDirtyRect_max_x}, .y: {aDirtyRect_max_y} }},")
print("};")
aDirtyRect = "&aDirtyRect"
else:
aDirtyRect = "nullptr"
print()
print("wr_moz2d_render_cb(")
print(f" mozilla::wr::ByteSlice {{ .buffer: blob_buffer, .len: {blob_len} }},")
if aFormat in WR_IMAGEFORMATS:
print(f" mozilla:wr::ImageFormat::{WR_IMAGEFORMATS[aFormat]},")
else:
print(f" {aFormat}, // mozilla:wr::ImageFormat::?")
print(" &aRenderRect, &aVisibleRect,")
if aTileSize or aDirtyRect_notnull:
print(f" {aTileSize}, {aTileOffset},")
print(f" {aDirtyRect},")
else:
print(f" {aTileSize}, {aTileOffset}, {aDirtyRect},")
print(
f" mozilla::wr::MutByteSlice {{ .buffer: output_buffer,"
f" .len: {output_len} }});"
)
if __name__ == "__main__":
main()
|