#!/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()