pure-zstd/test/fse_interleaved_test.dart

55 lines
2.4 KiB
Dart
Raw Normal View History

import 'dart:typed_data';
import 'package:pure_zstd/src/bit_reader.dart';
import 'package:pure_zstd/src/exception.dart';
import 'package:pure_zstd/src/fse.dart';
import 'package:test/test.dart';
/// `fseDecodeInterleaved` has no symbol count to stop on: it runs until the
/// bitstream is spent, so the only thing keeping it inside the caller's
/// buffer is its own room check. Both of its exhausted branches write a third
/// symbol in the same pass, so a check for two let `at` reach `outLimit`,
/// which is one past the end.
///
/// `HuffmanTable` calls it with a 256-byte buffer, so overrunning it indexes
/// `_weights[256]`. This is the same reproducer as the 53-byte frame in the
/// corpus, with the frame stripped away: the weight table description and the
/// bitstream the block carried, handed straight to the function.
void main() {
group('fseDecodeInterleaved', () {
// The two bytes are the whole FSE table description: accuracy log 5 and a
// distribution that gives the stream below two symbols per state pair.
final description = Uint8List.fromList([0x10, 0x3F]);
// 33 bytes of 0xAA and then the end marker, which is the stream the
// crafted block put after the description.
final stream = Uint8List.fromList([...List.filled(33, 0xAA), 0x02]);
test('refuses a stream longer than the caller has room for', () {
final table = FseTable(6);
expect(readFseTable(table, description, 0, description.length, 255), 2);
final bits = ReverseBitReader()..reset(stream, 0, stream.length);
final weights = Uint8List(256);
expect(
() => fseDecodeInterleaved(table, bits, weights, 0, weights.length),
throwsA(isA<ZstdException>()),
);
});
test('fills the buffer exactly when there is room for the last pass', () {
final table = FseTable(6);
readFseTable(table, description, 0, description.length, 255);
// Same stream, a buffer with slack. The count it returns must be the
// symbols it actually wrote, so the last pass cannot have been longer
// than the room the check left.
final bits = ReverseBitReader()..reset(stream, 0, stream.length);
final room = Uint8List(1024);
final written = fseDecodeInterleaved(table, bits, room, 0, room.length);
expect(written, greaterThan(256));
expect(written, lessThanOrEqualTo(room.length));
});
});
}