"""Read version-4 Luau chunks without executing them. Layout: upstream Luau VM/src/lvmload.cpp, Common/include/Luau/Bytecode.h. Only v4/type1 is accepted; later/custom layouts fail instead of guessing. """ import argparse import json import struct from pathlib import Path def inspect(path): data = Path(path).read_bytes() offset = 0 def read(size): nonlocal offset value = data[offset:offset + size] if len(value) != size: raise ValueError('truncated chunk') offset += size return value def byte(): return read(1)[0] def integer(): value, shift = 0, 0 while True: v = byte() value |= (v & 127) << shift if v < 128: return value shift += 7 if shift > 28: raise ValueError('oversized integer') if (byte(), byte()) != (4, 1): raise ValueError('only Luau v4/type1 supported') strings = [None] + [read(integer()).decode('utf-8', 'replace') for _ in range(integer())] protos = [] for index in range(integer()): stack, params, upvalues, vararg, flags = [byte() for _ in range(5)] read(integer()) code = [struct.unpack('> gap) + 1) * 4) locals_ = [] ups = [] if byte(): for _ in range(integer()): locals_.append([strings[integer()], integer(), integer(), byte()]) ups = [strings[integer()] for _ in range(integer())] protos.append(dict(index=index, name=name, line=line, stack=stack, params=params, upvalues=ups, children=children, constants=constants, code=code, locals=locals_)) main = integer() if offset != len(data): raise ValueError(f'unconsumed bytes: {len(data) - offset}') return dict(main=main, strings=strings, protos=protos) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('path') parser.add_argument('--output', required=True) args = parser.parse_args() Path(args.output).write_text(json.dumps(inspect(args.path), indent=2, ensure_ascii=False), encoding='utf-8')