#!/usr/bin/env python3 # test-repeat-range.py # # Regression test for F-12872: repeating the -r option in squashelf # replaced the ranges array without freeing the previous one (leak) and # silently discarded the earlier ranges. A second -r must now be # rejected; a single comma-separated list remains the way to pass # multiple ranges. # # Copyright (C) 2026 wolfSSL Inc. # # This file is part of wolfBoot. # # wolfBoot is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # wolfBoot is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA import os import struct import subprocess import sys import tempfile EHSIZE = 64 PHSIZE = 56 def make_elf64(path, paddr, memsz, filesz=0x10): ph_off = EHSIZE seg_off = ph_off + PHSIZE ident = b"\x7fELF" + bytes([2, 1, 1, 0]) + b"\x00" * 8 # ELF64, little-endian ehdr = ident + struct.pack( " 1 else "./squashelf" rc = 0 with tempfile.TemporaryDirectory() as d: elf = os.path.join(d, "in.elf") make_elf64(elf, paddr=0x50, memsz=0x100) # 1) A second -r must be rejected: pre-fix it succeeded, leaking # the first array and silently filtering on the second range # only. The second range alone keeps the segment, so a # pre-fix run exits 0 (accepted) while a post-fix run exits # non-zero (rejected). if run(squashelf, ["-r", "0x400-0x500", "-r", "0x0-0x200"], elf, os.path.join(d, "dup.out")) == 0: print("FAIL: repeated -r option was accepted") rc = 1 else: print("PASS: repeated -r option rejected") # 2) Regression guard: a single comma-separated range list must # still work (the filter keeps a segment only when both its # start and end fall inside one of the ranges). if run(squashelf, ["-r", "0x0-0x200,0x400-0x500"], elf, os.path.join(d, "list.out")) != 0: print("FAIL: comma-separated range list was rejected") rc = 1 else: print("PASS: comma-separated range list accepted") sys.exit(rc) if __name__ == "__main__": main()