Skip to content

Commit 306016c

Browse files
sbryngelsonclaude
andcommitted
Harden binary reader: EOF check, header validation, varname union, stacklevel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ec1d590 commit 306016c

1 file changed

Lines changed: 9 additions & 3 deletions

File tree

toolchain/mfc/viz/reader.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ def _detect_endianness(path: str) -> str:
5656
"""Detect endianness from the first record marker (should be 16 for header)."""
5757
with open(path, 'rb') as f:
5858
raw = f.read(4)
59+
if len(raw) < 4:
60+
raise EOFError(f"File too short to detect endianness: {path}")
5961
le = struct.unpack('<i', raw)[0]
6062
if le == 16:
6163
return '<'
@@ -99,6 +101,10 @@ def read_binary_file(path: str, var_filter: Optional[str] = None) -> ProcessorDa
99101
# Record 1: header [m, n, p, dbvars] — 4 int32
100102
hdr = _read_record_endian(f, endian)
101103
m, n, p, dbvars = struct.unpack(f'{endian}4i', hdr)
104+
if m < 0 or n < 0 or p < 0 or dbvars < 0:
105+
raise ValueError(
106+
f"Invalid header in {path}: m={m}, n={n}, p={p}, dbvars={dbvars}"
107+
)
102108

103109
# Record 2: grid coordinates — all in one record
104110
grid_raw = _read_record_endian(f, endian)
@@ -304,7 +310,7 @@ def assemble_from_proc_data( # pylint: disable=too-many-locals
304310
else:
305311
global_z = np.array([0.0])
306312

307-
varnames = list(proc_data[0][1].variables.keys())
313+
varnames = sorted({vn for _, pd in proc_data for vn in pd.variables})
308314
nx, ny, nz = len(global_x), len(global_y), len(global_z)
309315

310316
global_vars: Dict[str, np.ndarray] = {}
@@ -372,12 +378,12 @@ def assemble(case_dir: str, step: int, fmt: str = 'binary', # pylint: disable=t
372378
fpath = os.path.join(case_dir, 'binary', f'p{rank}', f'{step}.dat')
373379
if not os.path.isfile(fpath):
374380
import warnings # pylint: disable=import-outside-toplevel
375-
warnings.warn(f"Processor file not found, skipping: {fpath}")
381+
warnings.warn(f"Processor file not found, skipping: {fpath}", stacklevel=2)
376382
continue
377383
pdata = read_binary_file(fpath, var_filter=var)
378384
if pdata.m == 0 and pdata.n == 0 and pdata.p == 0:
379385
import warnings # pylint: disable=import-outside-toplevel
380-
warnings.warn(f"Processor p{rank} has zero dimensions, skipping")
386+
warnings.warn(f"Processor p{rank} has zero dimensions, skipping", stacklevel=2)
381387
continue
382388
proc_data.append((rank, pdata))
383389

0 commit comments

Comments
 (0)