tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

moz2d_bin2cpp.py (4207B)


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