Skip to content

Releases: shunnag/KaitoKit

KaitoKit 0.13.0

Choose a tag to compare

@shunnag shunnag released this 10 Oct 08:19
d9eaada

復号並列数の公開設定と、decoder・暗号・ハッシュ・展開 I/O の高速化をまとめた release。

追加

  • ReaderOptions.decodeThreads を追加。nil は CPU 構成・物理メモリ・電力方針から自動で決め、
    明示値は ReaderOptions.decodeThreadsRange(1...1024)に丸める。自動値は open 時に固定し、reopen に引き継ぐ。
    ReaderOptions.automaticDecodeThreads(powerPolicy:) で現在の自動値を取得できる。
  • ReaderOptions.decodePowerPolicy と公開 enum DecodePowerPolicy を追加。
    既定の .reduceInLowPowerMode、温度上昇時も減らす .reduceInLowPowerModeOrThermalPressure、
    電力・温度による削減をしない .alwaysUseAllCores を選べる。明示した並列数には作用しない。
  • ReadLimits.parallelDecodeMemory を追加。nil は物理メモリの 50% を並列復号の保持予算にする。
    CPU 構成を取得する CPUTopology を @_spi(Parallelism) で公開し、process 共通の leaf decode pool が
    実行中の job 数を active logical CPU 数以下に保つ。
  • kaito の list / sha / extract / bench に --threads N|auto、sha に --sink を追加。
    sha --sink は SHA-256 の計算を省き、同じ entry を読み切って byte 数を集計する。
  • Tests/Measurement/decode-ab/ に固定 seed の corpus 生成器と A/B 計測 harness を追加。
    通常の kaito sha の一致を先に確かめ、交互順の別 process 計測を JSONL に保存する。
    高精度 wall time・peak RSS・取得できる性能 counter と best / median / round 比を記録する。

変更

  • README を採用・導入向けに整理し、詳細を 対応形式、
    制限、組み込み、
    CLI、開発 に分けた。
    既存の日英の説明・表・検証記録へのリンクを保持した。

  • CI の build を Xcode 27 / Swift 6.4 のみにした。Swift 6.3.3 の -O による
    TaskLocal<function?> の誤コンパイルを避け、macOS 26 以上、Apple Silicon / Intel の実行対応は維持する。
    Xcode 27 で universal build した二つの test bundle・kaito・xctest と依存 framework / dylib を
    macos-26 / macos-26-intel に運び、コンパイルせず全 suite と Asia/Tokyo の LHA golden を検査する。
    cooViewer が Xcode 26 で使う framework script の旧 module 配置の分岐は残す。

  • XZ / bzip2 の固定 8 worker / 512 MiB 上限をなくし、自動並列数・共通 pool・保持予算に従う。
    圧縮 tar / cpio の staging に加え、単独 .xz / .bz2 stream も並列復号する。

  • 複数 frame の zstd、複数 member の lzip、pbzx の chunk を並列復号し、入力順に出力する。
    単一単位、サイズが不明、予算不足の場合は直列経路に戻す。

  • UDIF(DMG)の後続 chunk を並列に先読みする。検索と LRU 更新が O(1) の cache にし、
    復号中は lock を解放する。同じ chunk の重複復号を防ぎ、先読みの error は要求時に返す。

  • LZ4 の履歴・出力を再利用する flat buffer にまとめ、literal / match をワイドコピーする。
    XXH32 は非整列 load、BLAKE2s / BLAKE2sp は block ごとの allocation を省く。

  • AES-CBC の任意位置読み取りを直前の暗号 block を含む一括読みにし、CommonCrypto の CBC で復号する。
    WinZip AES-CTR は二つの UInt64 で counter を更新し、鍵流 buffer を再利用する。

  • Deflate64 の Huffman 復号を 64-bit reservoir と一次・二次 table にする。
    zstd は必要な時だけ bit reservoir を補充し、長い match を 32 byte 単位でコピーする。

  • PPMd H / I の arena accessor と復号 loop を高速化し、検証済み field の参照と入力 buffer を再利用する。

  • RAR5 の非 solid entry は既知の展開サイズに合わせて window を縮小し、不要なゼロ初期化を省く。
    Huffman の quick table を 10 bit にする。LZMA / LZMA2 も entry ごとの入力領域と初期化を小さくする。

  • 展開の write buffer を最大 1 MiB にし、圧縮入力 chunk を範囲長に合わせる。
    extract / drain は chunk ごとに取消しを検査する。

修正

  • consumer はまず1 poll interval(50 ms、broadcast で早く戻る)待って Dispatch に実行機会を譲り、
    結果がまだなく、自分の leaf job が未開始なら inline で実行し、reader 数が active CPU 数以上など、
    待機する reader が全 thread を占有しても復号が deadlock しないようにした。

  • 文書の古い制限記述を訂正した。BIN/CUE の raw sector image は対応済みのため、
    制限 と日英の移行ガイドから ISO raw sector image の「未対応」を除いた。
    英語の LZMA_Alone の拡張子を .lzma のみから .lzma / .tlz に訂正した。

  • 制限 umask の互換テストが子 process でも現在の xctest を使い、SIP で消える DYLD_* を
    shell 内で復元する。同梱した Xcode 27 runner で macOS 26 上の試験を継続できる。

展開 byte 列・既存の error と ReadLimits は維持し、worker 数で出力は変わらない。
並列数を増やすと保持予算内でメモリ使用量が増える。M4 Max の 256 MiB の単独 .xz は
自動要求 16 threads で peak RSS が約14 MB → 約300 MB になった。
既知の小さな性能後退は非圧縮性の multi-block tar.xz の約5 ms。
8 → 16 worker ではメモリ帯域が律速になる。絶対値は機械と入力に依存する。
56 書庫の通常の kaito sha はすべて一致した。
decode 性能の検証記録と生データ。

KaitoKit 0.12.1

Choose a tag to compare

@shunnag shunnag released this 30 Sep 11:34

LHA / tar の解析・entry 公開・編集用配置復元と、入力から形式別 reader を作る処理の責務を整理した。
公開 API・書庫の受理条件・entry の公開値・decoder の hot loop は維持する。

変更

  • LHA の構造と境界の検査を LHAHeaderParser、名前と metadata の公開を LHAEntryPublisher に分けた。
  • tar の header / 拡張解析、entry 公開、編集用 snapshot の配置復元を専用の担当へ分けた。
    解析結果と COW の layout storage の共有を保ち、reopen ごとに読み直さない。
  • OpenedArchiveInput が source・nominal URL・実際に開いた volume・directory anchor・検出 hint を区別し、
    FormatReaderFactory が形式別 reader を組み立てる。password・出力予算・抽出 provenance は reopen ごとに独立する。
  • tar と RAR5 の同一の抽出 path 正規化を ArchivePath に集約した。
    root / DOS drive の扱いが異なる LHA は形式内の規則を保つ。
  • LHA の DOS 日時変換を parse ごとに再利用する。不正日時は従来どおり nil、Unix 拡張は優先する。
    release CLI の交互 A/B では、10,000 entry の LHA level 0 の open が ASCII で約22%、CP932で約11%短縮した。

全1,599件のローカルテストは0失敗(既存50 skip)。macOS 26 / Intel / Xcode 27 の全CI、
両framework構成、圧縮payloadのsanitizer検証と Asia/Tokyo の LHA golden比較も成功した。
7種の計測入力の SHA 出力はすべて一致した。この計測は metadata / read 経路を対象とし、全codecやGUI全体の性能を表さない。
責務・互換性・性能の検証記録。

KaitoKit 0.12.0

Choose a tag to compare

@shunnag shunnag released this 29 Sep 16:40
6b72047

圧縮 tar / cpio の staging の並列復号(xz の block 並列 ParallelXZDecompressor、単一 stream bzip2 の block 単位 Bzip2BlockScanner)と、
2026-09-28 のコード品質レビューに続く source の配置整理をまとめた release。公開 API・@_spi の宣言・書庫の読み取り結果は変えていない。
挙動の変わる点は各節の「挙動の変わる点」に列挙する(.taz の fallback 名、到達しにくい error 文言、不正な ByteSource への error)。
計測と判断は Documentation/verification/2026-09-29-parallel-decoders.md と 2026-09-29-deferred-items.md に記録した。
GyoshukuKit 0.7.0 はこの版を .upToNextMinor(from: "0.12.0") で参照する。

追加

  • 圧縮 tar / cpio の xz staging を block 並列にした(ParallelXZDecompressor)。xz -T0 や GyoshukuKit が書く複数 block の stream を、
    検証済みの block 表から連続 block の run ごとに従来の XZDecompressor で独立に復号し、順に出力する。出力と tar の区切りの地図は
    直列経路と同一。単一 block、連結 stream、保持量の上限(512 MiB、W < 2)では従来の直列経路に渡す。M4 Max の 256 MiB の text の tar.xz
    (11 block)で kaito sha が 2.1 s → 0.5 s。
  • 圧縮 tar / cpio の bzip2 staging が単一 stream の中でも block 単位で並列に復号する。bit 単位の block magic を探し、連続 block の run を
    独立した stream に組み直して libbz2 に渡す(Bzip2BlockScanner)。出力と tar の区切りの地図は直列経路と同一、失敗時は stream の始点
    から従来の decoder で読み直す。M4 Max の 256 MiB の text の tar.bz2(bsdtar、単一 stream)で kaito sha が 5.8 s → 1.05 s。

変更

  • ソースの配置を機能ごとに整理した。公開 API・@_spi の宣言・書庫の読み取り結果は変えていない。
    • 形式に依存しない部品を Core/ に集めた: 固定幅 field の読み取り(ByteFields)、FILETIME / Mac / DOS の日時変換
      (Timestamps)、metadata 予算、path の component 分割、ASCII 数字、byte 範囲、CRC-16/XMODEM、XXH32 / XXH64、
      Blake2、CommonCrypto の pointer 境界(CommonCryptoPrimitives)と定数時間比較、書き出しの EINTR 再試行。
    • ArchiveReader の初期化を形式の検出・reader の生成・圧縮 stream の container 化に分け、FormatReader に
      reopened(options:) と validateEncryptionSupport(for:) を足して型ごとの分岐を protocol に置き換えた。
      FormatDetector の LHA / RAR の署名走査は Formats/LHA/LHASignatureScanner.swift / Formats/RAR/RARSignatureScanner.swift に置く。
    • 大きな reader を役割ごとの型に分けた: ZIP(ZipCentralDirectoryLocator / ZipCentralDirectoryParser / ZipExtraFields /
      ZipLocalHeaderRecovery)、RAR4 / RAR5(VolumeParser / EntryPublisher / Structures / SolidCoordinator)、
      7z(SevenZipHeaderDecoder / SevenZipStreamsParser / SevenZipFolderCoordinator / SevenZipMethod)、
      tar(TarHeaderBlock / TarPAXRecords / TarSparse)、LHA(LHAExtendedHeader)、StuffIt X の reader。
    • codec を形式の directory から Codecs/ に、container の枝を形式の directory に移した: gzip / xz / brotli / LZW / lzip / pbzx の
      decompressor と Deflate64Decompressor は Codecs/、CAB の folder decoder(MSZIP / LZX)は Formats/Cab/、
      Formats/Wrappers/ は Formats/MacEnvelope/・Formats/AppleDouble/・Formats/StuffIt/StuffItSplitSet.swift に、
      HFS+ は Formats/HFSPlus/、7z の filter は Codecs/SevenZipFilters/、bzip2 は Codecs/Bzip2/、XPRESS は Xpress、
      StuffIt X JPEG は Codecs/StuffItX/JPEG/。tar splice の部品は Reader/TarSplice/。
    • 名前の文字コード判定を JapaneseNameEncodingResolver / LetterRules / NameOrthography に分け、採点の調整値を
      NameEncodingScorer.Tuning に、字母の種類を AlphabetFlags に集めた。Formats/ArchiveNameResolver が書庫全体の
      名前判定を一つにする。
    • kaito の各 command を Sources/kaito/Commands/ に分けた。KaitoKitCompat の複写器と hard link の展開を型に分け、
      KaitoArchive の三つの initializer は convenience になった(名前・引数・結果は同じ)。
    • 経緯を書いていた comment を現在の契約に書き換え、review 回や milestone の符号を検証記録の path に置き換えた。
      magic number に名前を付け、test だけが使う API を test target へ移した。
  • テストの共有 helper を Tests/KaitoKitTests/Support/ に集め(TestFixtures・KaitoCLI・Digests・HexBytes・ExternalTools・
    KaitoErrorAssertions・DecompressorDraining・LittleEndianBytes ほか)、test file を形式ごとの directory に分け、
    milestone 名の test class を機能名に改めた(FormatDetectorTests・StreamingDecompressorTests・ZipEndRecordHardeningTests・
    NameSafetyRegressionTests・DocumentationConsistencyTests・LHAExternalCorpusTests ほか)。計測の道具は Tests/Measurement/、
    Sources へ生成物を書く generator は Scripts/generate/ に置き、Tests/README.md に環境変数と外部ツールの一覧を書いた。
    Compat のテストは Tests/KaitoKitCompatTests/CompatFixtures.swift を使う。
  • 挙動の変わる点(error の文言、到達できない経路、既定の上限でしか届かない境界):
    • ArchivePath.components は component 数が上限とちょうど等しい path の末尾の //(例: 上限 2 の "a/b//")と、
      上限 0 の "/" を受け入れる。rpm と xar の旧 split(maxSplits:) はこれを拒否していた。既定の上限 1,024 でのみ観測できる。
    • 到達できない error 文言の統一: "negative ZIP/detector read size" → "negative byte-range size"、"temporary-file buffer has no
      storage" → "write buffer has no storage"、"xar decoder byte count" → "decoder byte count"。zstd の到達できない default: は削除。
    • 不正な DOS 日時の error 文言が形式に依らず "invalid DOS timestamp" になった(ZIP は "invalid ZIP DOS timestamp"、
      RAR4 は "invalid RAR4 DOS timestamp" だった)。
    • KaitoKitCompat の安全でない path の拒否文言が Extractor と同じになった("absolute or empty entry path" /
      "entry path contains an unsafe component" / "empty entry path")。
    • 要求より多い byte を返す ByteSource に対して FormatDetector と LZMA2 の外側 reader が .truncated / .malformed
      を投げるようになった(正しい ByteSource では起きない)。
    • kaito の usage 表示が detect-encoding の --check-orthography を含む。
    • CAB の path component は Character ではなく UTF-8 の / で分ける(結合文字が / に続く名前だけで違いが出る)。
  • 2026-09-29 の追加整理。公開 API・@_spi・復号結果は変えていない。
    • 7z と RAR の AES-CBC random access 復号を Core/AESCBCRandomAccess に一つにした。RAR4 / RAR5 の solid coordinator・範囲
      decompressor・password 判定を generic な Formats/RAR/RARSolidCoordinator に一つにした(error 文言は形式名の label で不変)。
    • FormatDetector の EOCD 走査は ZipEndRecords.findEndRecords を使い、検出側は ZIP64 の番兵除外と基点 0 の判定だけを持つ。
    • Deflate・bzip2・gzip・xz・brotli の wrapper が持っていた入力 buffer の補充を Core/ChunkedSourceInput に一つにした。
    • LArc -lz5- の窓の seed と LZHUF の位置符号長を Codecs/OkumuraLZSSSeeds に置き、LArc・LZHUF・StuffIt LZAH が共有する。
    • 圧縮単一 file の接尾辞の表を Formats/SingleFile/CompressedNaming に一つにし、SingleFileReader と ArchiveReader が同じ表を読む。
    • RAR3 / RAR5 / Blake2 のテスト専用 API に印を付け、呼び手のない Data 版の鍵導出を二つ削った。
  • 挙動の変わる点:
    • .taz の単一 entry の fallback 名が x.taz から x.tar になった(container の表と同じく tar の別名として扱う)。
      .tar.bz は従来どおり単一 entry のまま(.bz は名前から除くだけで container の別名にはしない)。
    • 要求より多い(または負の)byte 数を返す ByteSource に対して Deflate・bzip2 の wrapper が投げる error が
      .malformed("ByteSource returned an invalid byte count") から .truncated になり、gzip・xz・brotli と同じになった(正しい ByteSource では起きない)。
  • 2026-09-29 の残り整理(後回しの項目をなくす round)。公開 API・@_spi・復号結果は変えていない。
    • Formats/LHA/LHAExtendedHeader.swift の型を file 名と同じ LHAExtendedHeader にし、Text/ の NameEncodingScorer の extension file を
      NameEncodingScorer+LetterRules.swift / NameEncodingScorer+NameOrthography.swift にした。TarReader の 512 literal は TarHeaderBlock.size。
    • Codecs/PPMd/ を VariantH/(PPMd7・7z / RAR の range decoder)と VariantI/ に分けた(file の中身は不変)。
    • 883 行の ZipCentralDirectoryLocator.swift を、候補の選択(同 file)・回復の判定(ZipEndRecordRecovery.swift)・
      directory の位置計算(ZipDirectoryLocationResolver.swift)に分けた。関数の本体・error の順序・回復の予算は同じ。

KaitoKit 0.11.0

Choose a tag to compare

@shunnag shunnag released this 27 Sep 18:04
bbfd397

GyoshukuKit の編集用 SPI ZipRawLayout / TarEditLayout / LHARawLayout / SevenZipEditLayout と、
ZIP・zstd の高速化をまとめた release。新しい宣言はすべて @_spi で、公開 API・公開 enum の変更は無い。
SPI は SemVer の対象外だが、0.x の間は追加だけとし、破壊的変更は GyoshukuKit と同時に release する。
取消し済み Task からの open の挙動変更と既知の性能制限は以下に記載する。

変更

  • ArchiveReader.open(URL / Data / ByteSource などの open 経路)は、既に取消し済みの Task 内から
    呼ぶと、最初の record(index 0)の取消し検査で CancellationError を投げる。
    KaitoKitCompat の failable initializer はこの場合も nil を返す。
  • ZIP 中央ディレクトリ解析で DOS timestamp の変換と Calendar の再利用を改善し、
    500,000 entry の open を 1,142 ms から 463 ms へ短縮した(d412a02)。
    ZIP / tar / 7z / RAR / ISO / UDF / StuffIt / WIM / xar の長い metadata 走査で
    1,024 record ごとに取消しを検査し、ZIP64 と UDF → ISO の再試行でも CancellationError を保持する。
  • zstd の最初の高速化で 256 MiB text.tar.zst の open を 1,449 ms から 513 ms へ短縮した
    (約 3 倍、b518014)。検証記録。
  • zstd の sequence / Huffman 復号を高速化し、作業領域と表を frame ごとに再利用、block 出力を view 化する(P11 Stage 3)。
    静穏条件の最終 host gate は通過。text.tar.zst の open は 0.558 倍(上限 0.70)、
    small-zstd.zip の展開は 0.388 倍(上限 0.55)、headers-zstd.zip は 0.440 倍(上限 0.65)。
    RSS も before + 1 MiB の上限内。出力・検査・公開 API を維持する。
    検証記録。
  • GyoshukuKit の 7z 編集用に SevenZipEditLayout SPI を追加。
    recordsSevenZipEditLayout(既定 false)で生の header 値を記録し、source を持たない snapshot を返す。
    reopen() は記録を共有する。AES が直接読む packed stream の復号も既存の鍵 cache で提供し、
    展開や出力 CRC の照合は行わない。既存の公開 API・値・検査・エラーは維持する。
    検証記録。
  • GyoshukuKit の LHA 編集用に LHARawLayout SPI を追加。member の header / data 範囲、
    level・method・OS ID・CRC16、公開 entry との対応、SFX 開始位置と終端を返す。
    終端後の byte は最大 65,536 byte だけ読み、recovery・分割巻・LHA 以外では nil。
    reopen() は解析済み record を共有し、既存の公開値・受理条件・LHA の rawRecord(of:) == nil は維持する。
    0.x の SPI は追加だけとし、破壊的変更は GyoshukuKit と同時に release する。
    検証記録。
  • TarEditLayout SPI に、opt-in の tar member 配置、gzip / bzip2 / xz の区切りと圧縮 byte の CRC-32、
    復号済み image と元の記述子を共有する編集用 snapshot を追加。reopen() は再読せず共有する。
    圧縮 tar / cpio の bzip2 staging は上限付きで並列復号し、境界を検証できない区間から直列へ戻す。
    ReaderOptions.recordsTarEditLayout の既定は false。有効時の圧縮 tar の reopen は元の圧縮 source の
    記述子も保持する。既存の公開値と公開 API は維持し、0.x の SPI は追加を基本とする。
    openSplicedCompressedTar は区切りの digest・辞書・枠を検証し、再利用する image の葉を共有する。
    CompressedTarSplice と理由付きの TarSpliceVerificationError を追加。K5 の snapshot は option に依らず作る。
    mixed の追加の K5 / 全体 open 比は 0.298 / 0.213 / 0.085(tgz / tbz / txz、負荷付き計測)。
    既知の性能制限として、tbz の大削除の K5 / 全体 open 比は実測 0.432 で目標 0.25 を上回る。
    静穏条件での再計測記録は無く、この未達値を制限として扱う。
    段階 A の計測と検証記録・
    段階 B の計測と検証記録。
  • ZipRawLayout SPI に暗号方式・保存 CRC・実圧縮方式と、保存 payload の復号 stream を追加。
    ZipAESKeyMaterial で導出を並行実行でき、材料を渡す読取は password provider と鍵 cache を使わない。
    AES の verifier / HMAC と展開 stream の CRC 照合は維持する。ZipCrypto の保存 stream は 1 byte の
    照合値だけを検査するため、呼出側で展開後の CRC を検証する。既存の公開値・API は変更しない。
  • ZIP の公開値・検証・エラー・取消しの挙動を維持し、GyoshukuKit 用の ZipRawLayout SPI を追加。
    index から検証済みの生レコード範囲と local / CD の ZIP64 marker を取得できる。公開 rawRecord(of:) の
    同一性検査は維持する。SPI は SemVer の対象外だが、0.x の間は追加だけとし、破壊的変更は GyoshukuKit と
    同時に release して依存の下限を上げる。
  • ZIP の local header を最大 256 KiB の前方窓で読み、CD 解析時の formatSpecific を 8 枠の cache で共有。
    pathComponents は一回の走査と directory prefix の再利用で分割し、CRC の 16 進表記も直接構築する。
    splitter 単独で 500k の解析を 18.5–23.5% 短縮。2,000 件の小さな UT / descriptor 書庫では local 読み取りが各 3 回、
    一様な 1,000 件の辞書 storage は 1 個。
    500k の 3 corpus で SPI 全件走査は 136.6–201.2 ms(基準公開 raw の 14.0–15.3%)、CLI open は 246.3–324.8 ms。
    検証記録に基準との公開値比較と計測を記載。

KaitoKit 0.10.0

Choose a tag to compare

@shunnag shunnag released this 24 Sep 00:51
3f595ad

分割巻の情報を取得する公開 API ArchiveReader.volumeSet と ArchiveVolumeSet を追加した release。公開 enum の
case 追加は無く、利用側の網羅的 switch は変更不要。既定の検出・読み取りの挙動と巻数上限 128 は変更しない。
対象範囲と検証結果は検証記録を参照。

  • ArchiveReader.volumeSet と ArchiveVolumeSet を公開した。URL から連結した .001 系と native ZIP の分割巻について、論理順の URL・保持 fd の fstat による同一性・開いた巻と入口の位置を取得できる。名前だけの parse(fileName:) と、桁幅・大小文字を保つ巻名生成(ZIP の巻数変更にも対応)を追加。reopen() は同じ source の巻情報を引き継ぐ。単一ファイル・Data / ByteSource・StuffIt 固有の分割・.cue は対象外。検出・読み取りの挙動と既定の巻数上限 128 は変更しない。

KaitoKit 0.9.0

Choose a tag to compare

@shunnag shunnag released this 22 Sep 13:23
ad5547a

KaitoKit 0.9.0

対応済み形式の中で残っていた「読めないメソッド」を埋めた feature release です。公開 API の破壊的変更はありません(ArchiveFormat の case 追加なし)。既定の挙動が変わる点が 3 つあります(下記)。詳細は CHANGELOG.md と Documentation/verification/ の 2026-09-22 の記録を参照してください。

追加したメソッド

  • HFS+ decmpfs(Apple Disk Image / 生の HFS+ image): UF_COMPRESSED の file の本文を読めるようにしました。attributes B-tree の com.apple.decmpfs から実サイズと type を取り、type 1 / 3 / 4 / 7 / 8 / 9 / 10 / 11 / 12(stored / zlib / LZVN / LZFSE、inline xattr と resource fork、64 KiB chunk)を展開します。type 5 / 13 / 14 と未知の type は一覧のみ。LZVN は Apple Compression の LZFSE block として復号します。
  • RPM の stripped cpio(07070X): rpm 6 の既定 payload(rpm 4.12 以降の 4 GB 超 file でも使われる)を、RPM header の tag から名前・サイズ・mode・mtime・symlink 先を復元して列挙・読取できるようにしました。hard link は非 ghost の最大 index が本文を持ち、%ghost は payload に現れません。FILEDIGESTS が SHA-256 の場合は完全読取時に検証します。
  • 7z の Deflate64 coder(method ID 04 01 09、7-Zip -m0=Deflate64)。
  • WIM の XPRESS chunk size 4〜64 KiB(LZX は 32 KiB のまま)。
  • tar の旧 GNU sparse(typeflag S): header 内の sparse 表と拡張 block 連鎖を展開します(pax GNU.sparse 0.0 / 0.1 / 1.0 は 0.8.0 から対応済み)。star / Solaris の sparse は引き続き非対応。
  • XZ の RISC-V filter(ID 0x0B) を malformed ではなく unsupportedMethod("XZ RISC-V filter") として報告します(復号は引き続き非対応)。

既定の挙動の変更

  • rpm 6 の package は、これまで圧縮 payload 1 件(<name>.cpio.zst など)として見えていたものが、中の file を直接列挙するようになります。
  • DMG / HFS+ の decmpfs file は uncompressedSize が nil ではなく実サイズになり、read / extract が成功します。methodDescription は HFS+ decmpfs (zlib|LZVN|LZFSE|stored) です。
  • typeflag S を含む tar は、これまで書庫全体が unsupportedMethod で開けませんでしたが、開けるようになります。

リリース前レビュー(R1〜R11)

タグ前に敵対的レビュー(6 観点 × 検証 3 lens、39 agent)を実施し、確認された 11 件をすべてこのリリースに含めて修正しました。うち 3 件は実装の不具合で、いずれも独立オラクルとの食い違いを実測しています。

  • R1(regression): decmpfs 対応で加わった attributes B-tree の走査が catalog と同じ単体 metadata 上限(16 MiB)を共有し、xattr の多い image が開けなくなっていました(xattr 付き 4,500 file の 369 KB image が Read limit exceeded、7-Zip は 4,500 file を一覧)。UF_COMPRESSED が無ければ走査せず、必要な場合は独立 budget を maxTotalMetadataSize で見ます。
  • R2: inline decmpfs の宣言サイズが未検査で、12 KB の入力が 1.09 GB を確保していました(修正後 RSS 14.7 MB、7-Zip は 5.6 MB)。HFS+ driver の境界どおり 65,536 は成功、65,537 は malformed。
  • R3: RPM stripped payload が 65,536 件を超える package を開けませんでした(66,067 file の rpm 6 package が失敗、rpm2cpio | bsdtar は全件一覧)。ZIP 中央 directory と同じ是正です。
  • R4〜R11: 回帰テスト 4 件(ガードを一時除去して検出力を確認)と文書整合 4 件。

再現手順と実出力は 2026-09-22-release-review-0.9.0.md。

検証

全件 1,403 件、失敗 0、skip 45(CI と同じ oracle 要求つきでも同一)。framework build(x86_64 + arm64)も確認しました。各項目に検証記録(Documentation/verification/2026-09-22-*.md)があり、黒箱オラクル(7-Zip 26.03、bsdtar、rpm2cpio、unar、xz、Python tarfile、macOS の HFS+ driver / hdiutil / ditto)と原本の SHA-256 で照合しています。Apple 製の実物 DMG / system file(zlib 499 chunk の 32 MB、LZVN 39 chunk)でも一致を確認しました。

KaitoKit 0.8.1

Choose a tag to compare

@shunnag shunnag released this 22 Sep 07:17
eb608c2

KaitoKit 0.8.1

0.8.0 の変更(v0.7.0..v0.8.0)に対するリリースレビュー(Codex の built-in reviewer)の指摘 14 件を修正した patch release です。公開 API の変更はありません。詳細は CHANGELOG.md と 検証記録を参照してください。

修正(process の異常終了 → 例外)

  • R1 ARJ: 7 byte 未満の CRC 正当な基本 header で file type を範囲外参照していた。
  • R2 CFB: version 4 の root mini-stream サイズが UInt64.max のとき sector 数の切り上げで overflow していた。maxEntrySize で検査し、overflow しない式にした。
  • R3 CFB: 偏った sibling tree(4,000 entry の左鎖)で再帰が stack を使い切っていた。明示的な stack による走査にした。
  • R4 CHM: Int.max を超える section ID の Int 変換で trap していた。
  • R5 UDIF: 2^55 sector を宣言した chunk の sector × 512 で overflow していた。検査付き乗算を chunk 解析前に移した。

修正(既定挙動の退行・検証漏れ)

  • R6 AppleDouble sidecar の除去・resource fork 挿入後の index へ、tar の hard link 参照先も写す。
  • R7 AppleDouble 候補(._name)の probe が未対応 method や破損で失敗しても書庫全体の open を失敗させず、候補を通常 entry として残す。
  • R8 resource fork の読み取り完了前に sidecar の stream を読み切り、CRC と終端を検証する。
  • R9 UDIF の圧縮 chunk を cache する前に decoder の終端を確定し、宣言長を超える出力を拒否する。
  • R10 lzip / pbzx / WIM / CFB / CHM / ARJ の署名を BinHex probe の除外に追加(stored stream に BinHex の説明文があっても native 形式で開く)。
  • R11 GNU sparse tar 0.1 の GNU.sparse.name を公開名・展開先に使う。
  • R12 ZIP Shrink の連続する部分クリアで、前回解放した未使用 code を再利用する。
  • R13 StuffIt 分割セットの巻数上限を次の part の存在確認後に検査し、上限ちょうどの完結セットを受理する。
  • R14 MacBinary / AppleSingle / BinHex の公開 entry 数(resource fork 込み)を maxEntryCount と照合する。

各件に修正前に失敗する回帰テストを追加。全件 1,393 件、失敗 0、skip 45(既存)。CI(macos-26 / macos-26-intel / xcode-27、framework、mutants)緑。

KaitoKit 0.8.0

Choose a tag to compare

@shunnag shunnag released this 21 Sep 20:52
fc36308

KaitoKit 0.8.0

0.7.0 以降の変更をまとめたリリースです。形式の追加を中心にしています。詳細は CHANGELOG.md と Documentation/verification/ の 2026-09-20〜22 の各記録を参照してください。

追加した形式

  • Apple Disk Image(UDIF .dmg / 生の HFS+ image): zlib / bzip2 / lzfse / lzma / raw の chunk、GPT / Apple Partition Map / bare volume、HFS Plus / HFSX の catalog(file、directory、symlink、hard link、resource fork)、extents overflow。UDIF 内の ISO 9660 / UDF は各 reader へ。
  • UDF 1.02〜2.60(sparable / virtual / metadata partition、symlink、Macintosh resource fork)。ISO 9660 との hybrid は UDF の木を優先。
  • WIM(stored / XPRESS / LZX、複数 image、ADS、hard link、reparse point、SHA-1 検証)。
  • Compound File(MS-CFB / OLE2: .msi .doc .xls …)。MSI の詰め込み stream 名を復元。
  • CHM(ITSF、LZX の reset interval)。
  • ARJ(stored と method 1〜3、DOS SFX)。
  • MacBinary / AppleSingle / BinHex 4 の単体(payload が StuffIt でないもの)。
  • lzip、brotli、pbzx。

既存形式の拡張

  • ZIP: Shrink (1) / Reduce (2〜5) / Implode (6)。__MACOSX/._* AppleDouble sidecar を既定で resource fork に統合(ReaderOptions.appleDoublePolicy)。
  • 7z: Zstandard coder 04F71101。x86 BCJ / ARM64 filter の符号境界の不具合を修正。
  • RAR5: file copy(rar -oi)の本文公開。
  • ISO 9660: zisofs、BIN/CUE 生 sector image(2352 / 2448 / 2336)、.cue からの open。
  • tar: GNU sparse。cpio: 圧縮 cpio(.cpgz など)。CAB: PE 内 SFX。StuffIt: classic の分割セット。

互換性

  • ArchiveFormat に 12 の case(.lzip .brotli .pbzx .udf .wim .macBinary .appleSingle .binHex .compoundFile .chm .arj .dmg)を追加しました。利用側の網羅的 switch には case の追加が必要です。
  • ReaderOptions.appleDoublePolicy の既定 .merge により、Finder 製 ZIP / macOS tar の entry 数と index が変わります(.expose で従来の一覧)。

主な非対応

DMG の ADC(UDCO)chunk・APFS・decmpfs 圧縮 file(Apple 製 DMG に多い)、ARJ の method 4 / garbled / multi-volume、WIM solid(LZMS)、UDIF の暗号化と分割。いずれも名前付きの unsupportedMethod になります。

KaitoKit 0.7.0

Choose a tag to compare

@shunnag shunnag released this 19 Sep 15:01
3e48efc

KaitoKit 0.7.0

0.6.1 以降の変更をまとめたリリースです。KaitoFinder 0.1.0 (2) はこの内容で公開されています。詳細は CHANGELOG.md と Documentation/verification/ の各記録を参照してください。

追加

  • LZ4: 現行 frame(単体・圧縮 tar・連結・skippable・独立/連続 block・XXH32)と legacy frame(8 MiB block・連結・圧縮 tar)の読み取り。外部辞書は非対応。
  • ZIP method 95 (XZ) / 20 (旧 Zstandard): 暗号化・分割・ZIP64・descriptor・辞書上限と接続。AES XZ の全 block 検査は認証済み圧縮入力を上限付きで一時保持し、暗号文の繰り返し読み取りを防ぎます。
  • 7z Swap2 / Swap4 filter: solid の member 境界・暗号化・分割を独立 7zz fixture で検証。
  • 圧縮 tar: .tar.lzma / .tlz / .tbz / .taz(大文字小文字を区別しない)を既存 codec と TarReader に接続。
  • 空 LHA: .lha / .lzh と正確な 1 byte 終端の組合せを空書庫として受理(全項目削除後の再編集向け)。

堅牢化(2026-09-19 リリース前レビュー K1–K12)

  • reopen() は ZIP・tar・7z・LHA の解析済み entry と位置情報を共有し、圧縮 tar は展開済み source を共有します(preview ごとの再展開を防止)。
  • 圧縮 tar の一時展開は chunk ごとに Task の取消しを確認し、ReadLimits.stagingFreeSpaceReserve(既定 1 GiB)で一時 volume の枯渇を抑えます。
  • 7z: header の KDF に累積上限 ReadLimits.maxSevenZipHeaderKDFWork、solid decoder の失敗時解放(CRC のない後続 member の破損読み出しを防止)。
  • StuffIt: SFX 候補 header の検証を maxMetadataSize の累積読み取り予算で制限、StuffIt X の auxiliary-only stream を maxEntrySize と照合して遅延検証。
  • XZ: 全 block・連結 stream の辞書を Apple Compression に渡す前に ReadLimits.maxDictionarySize と照合(単体・圧縮 tar / RPM・xar)。
  • tar: header cursor を 4 KiB に縮小し、PAX / GNU 拡張本文は直接範囲読み取り。サイズ上限 .max の overflow 回帰テストを追加。

互換性

  • ArchiveFormat に .lz4 を追加しました。利用側の網羅的 switch には case の追加が必要です。
  • ReadLimits に stagingFreeSpaceReserve と maxSevenZipHeaderKDFWork を追加しました(既定値あり、既存の初期化は変更不要)。
  • ArchiveReader.open(source:sourceURL:options:) を追加しました。ByteSource から開く際にファイル名のヒント(圧縮 tar の別名・単一ファイル entry 名)を渡せます。
  • それ以外の公開 API の変更はありません。

テスト基盤

  • XZResourceLimitTests が /opt/homebrew/bin/xz を固定していたため、Intel runner(/usr/local/bin/xz)の CI で 2 件が失敗していました。共有の resolver に揃えました(コード変更はテストのみ)。

KaitoKit 0.6.1

Choose a tag to compare

@shunnag shunnag released this 17 Sep 05:27
16929c2

KaitoKit 0.6.1

0.6.0 以降の修正 2 件をまとめたリリースです。詳細は CHANGELOG.md を参照してください。

修正

  • ZipCrypto の誤パスワード判定: 1 byte のヘッダ検査を誤通過したパスワードによる CRC 不一致・decoder の破損/入力不足を wrongPassword に正規化しました。7zAES と同様に、暗号化 stream 自体の破損も誤ったパスワードとして報告される場合があります。
  • 大規模 ZIP の初回解析: EOCD 候補の再試行予算が正当な大規模書庫の初回解析まで拒否していた不整合を修正しました。中央ディレクトリは既存の総 metadata 上限 maxTotalMetadataSize(既定 256 MiB)で制限し、初回候補の通常解析は課金免除、上限/未対応エラー後の整合性検査と再試行には累積 work の上限を適用します。分割 ZIP の整合性検査も新しい上限に対応しました。

互換性

  • 公開 API の変更はありません。