koni_archive_core 0.9.0
koni_archive_core: ^0.9.0 copied to clipboard
Core abstractions for the koni_archive ecosystem — byte sources, entry model, typed exceptions, checksums, and the format-detection registry.
Changelog #
0.9.0 - 2026-07-17 #
- Decompression-bomb guards on the read side.
ArchiveReadOptionsgainsmaxEntrySize(a cap, in bytes, on any single entry's decoded output) andmaxEntryCount(a cap on how many entries an archive may declare). Both are enforced at theArchiveFormat.openReaderseam, so they hold for every format and cannot be bypassed by using a reader directly instead of the facade: streaming an entry pastmaxEntrySizeaborts the decode withSizeLimitExceededException, and opening an over-count archive throws the same. Null (the default) means unbounded, so behavior is unchanged unless a caller opts in. maxContainerDecodeSizebounds a reader's bulk decodes that are not a single entry's stream — a layered.tar.gzdecompressed at open, or a 7z (compressed) header / solid folder decoded to reach an entry. For the.tar.gzopen-time decode it falls back tomaxEntrySizewhen unset, so a per-entry limit alone still guards against a gzip bomb at open; 7z's folder/header caps are opt-in only (a per-entry limit must not reject a small entry that merely lives in a larger solid folder). Both null leaves each format at its built-in behavior — a no-op for ZIP, plain TAR, and plain gzip; RAR does not yet enforce it (a documented gap on the solid-run decode).- SPI change (format implementers). The method a format overrides to build
its reader is now
ArchiveFormat.createReader;openReaderbecame the concrete entry point that wraps the reader with the guards above. A third-party format that overrodeopenReadermust rename it tocreateReader— a compile error points at it. Application code is unaffected. SizeLimitExceededExceptionnow also covers the entry-count limit; itslimitfield carries a byte count for a size limit or an entry count formaxEntryCount.
0.8.0 - 2026-07-16 #
ArchiveWriteOptionsgainsallowUnsafePaths(defaultfalse). When set, a writer skips thevalidateWritePathcheck and writes eachArchiveEntrySpec.pathverbatim, including absolute paths, drive letters, and..segments that escape the archive root. It exists to author a hostile archive on purpose, e.g. a fixture that exercises a consumer's path-traversal ("Zip Slip") defenses, which the safe writer refuses to build. Purely additive: the default keeps the existingArgumentErrorrejection, and the read side is untouched (every reader still normalizes paths at parse time and flagspathEscapedRoot, so reading such an archive back stays safe).
0.7.0 - 2026-07-16 #
ArchiveReadOptionsgainsnextVolume, a resolver a reader calls to obtain the later volumes of a multi-volume archive (volume 1 is the source passed to the reader;nextVolume(n)returns volumenor null when there is no such volume). Consumed by the RAR reader; other formats ignore it. Purely additive; existing callers are unaffected.
0.6.0 - 2026-07-15 #
- Phase 4 (write-side encryption):
ArchiveWriteOptionsgainspassword(whole-archive AES-256 encryption, honored by the ZIP and 7z writers) andencryptHeader(7z-mhe). Same encoding contract as the read side; no changes to the reader model. - First release published to pub.dev.
0.5.0 - 2026-07-15 #
- Phase 3 (decryption) API:
ArchiveReadOptions.passwordfor opening password-protected archives, andInvalidPasswordException(a subtype ofEncryptedArchiveException) for a wrong password where the format carries a check value.EncryptedArchiveExceptionnow also covers unsupported encryption schemes, not just "no password given".
0.4.0 - 2026-07-15 #
- P2-1: write API:
ByteSink(+BytesBuilderSink,FileByteSinkin io.dart),ArchiveEntrySpec,ArchiveWriter/ArchiveWriteFormatSPI,ArchiveWriteOptions, andvalidateWritePath(reject unsafe paths). Mirrors the read side; reuses the entry/compression enums, checksums, and exceptions. No format writers yet (TAR at P2-2).
0.3.0 - 2026-07-15 #
- Lockstep release; no changes since 0.2.0.
0.2.0 - 2026-07-15 #
- lockstep release; no changes since 0.1.0.
0.1.0 - 2026-07-15 #
- M7:
ArchiveReadOptions.entryNameDecoder(caller-supplied decoder for formats with unreliable name encodings);ByteReader.readUint64le/benow enforce a uniform 2^53 − 1 cap on every platform (fuzz-found: hostile fields could wrap negative on the VM). - M5:
Crc32upgraded to slicing-by-8 (~4x faster verified reads). - M4:
ByteSource.name(optional display name): lets formats derive entry names from the container (gzip FNAME fallback);FileByteSourcereports its path,MemoryByteSource/BlobByteSourceaccept an optionalname:. - M3:
ArchiveReadOptions(verifyChecksums) threaded throughArchiveFormat.openReaderand the registry driver; moreArchiveCompressionconstants (deflate64, bzip2, ppmd, zstd) for diagnostics. - M1: core abstractions.
ByteSource(seekable, pread semantics) withMemoryByteSource;FileByteSourcebehind opt-inio.dart;BlobByteSourcebehind opt-inweb.dart(dart2js + dart2wasm).ByteReader(sync parsing cursor; portable 64-bit reads, typed EOF errors) and incrementalCrc32/Adler32.- Typed exception hierarchy rooted at
ArchiveException, every type carrying format/offset/entry context. - Immutable
ArchiveEntrymodel (ArchiveEntryType,ArchiveCompressionwith raw-id-carryingunknown). normalizeEntryPath: separators, drive letters, absolute paths,./..resolution with root-escape flagging.ArchiveFormat/ArchiveReaderSPI andArchiveFormatRegistrywith detection driver (registration-order probing, first match wins, explicit-format escape hatch).
- M0: package scaffolding: pub workspace membership, shared strict lints, CI matrix (VM on Linux/macOS/Windows; web via dart2js and dart2wasm).