diff --git a/iso9660/iso9660.go b/iso9660/iso9660.go index ed1da63..995021e 100644 --- a/iso9660/iso9660.go +++ b/iso9660/iso9660.go @@ -198,15 +198,16 @@ func (iso *ISO9660) parsePathTable() error { iso.pathTable = nil i := 0 for i < len(pathTableRaw) { - if i >= len(pathTableRaw) { - break - } - dirNameLen := int(pathTableRaw[i]) if dirNameLen == 0 { break } + // Validate we have enough data for this entry (8 byte header + name) + if i+8+dirNameLen > len(pathTableRaw) { + return fmt.Errorf("truncated path table entry at offset %d", i) + } + // Extended attribute record length at i+1 (skip) dirLBA := binary.LittleEndian.Uint32(pathTableRaw[i+2 : i+6]) dirParentIdx := int(binary.LittleEndian.Uint16(pathTableRaw[i+6:i+8])) - 1 diff --git a/iso9660/iso9660_test.go b/iso9660/iso9660_test.go index aaf1a71..f0ffe52 100644 --- a/iso9660/iso9660_test.go +++ b/iso9660/iso9660_test.go @@ -545,3 +545,40 @@ func TestGetDataPreparerID(t *testing.T) { // Data preparer ID is at a different offset - our minimal ISO doesn't set it _ = iso.GetDataPreparerID() } + +// TestISO9660_TruncatedPathTable verifies bounds check for malformed path table entries. +func TestISO9660_TruncatedPathTable(t *testing.T) { + t.Parallel() + + tmpDir := t.TempDir() + + // Create a minimal ISO + isoData := createMinimalISO("VOL", "SYS", "PUB") + + // Corrupt the path table: set a directory name length that exceeds the path table size + // Path table is at block 18 (offset 18 * 2048 = 36864) + pathTableOffset := 18 * 2048 + + // Set directory name length to a large value (e.g., 100) that exceeds remaining data + // The path table entry format is: + // - byte 0: directory name length + // - byte 1: extended attribute record length + // - bytes 2-5: directory LBA (little-endian) + // - bytes 6-7: parent directory number (little-endian) + // - bytes 8+: directory name + isoData[pathTableOffset] = 100 // Large name length that would overflow + + isoPath := filepath.Join(tmpDir, "truncated.iso") + if err := os.WriteFile(isoPath, isoData, 0o600); err != nil { + t.Fatalf("Failed to write ISO: %v", err) + } + + // This should fail with a truncated path table error, not panic + _, err := Open(isoPath) + if err == nil { + t.Error("Open() should error for truncated path table entry") + } + if !strings.Contains(err.Error(), "truncated path table entry") { + t.Errorf("Open() error = %v, want error containing 'truncated path table entry'", err) + } +}