std/*io_transformer*: add "#truncated input"
name old speed new speed delta
wuffs_bzip2_decode_10k/clang11 58.5MB/s ± 0% 59.9MB/s ± 0% +2.50% (p=0.008 n=5+5)
wuffs_bzip2_decode_100k/clang11 45.7MB/s ± 0% 50.5MB/s ± 0% +10.66% (p=0.008 n=5+5)
wuffs_bzip2_decode_10k/gcc10 56.2MB/s ± 0% 61.9MB/s ± 0% +10.01% (p=0.008 n=5+5)
wuffs_bzip2_decode_100k/gcc10 46.5MB/s ± 0% 50.4MB/s ± 0% +8.41% (p=0.016 n=4+5)
wuffs_deflate_decode_1k_full_init/clang11 195MB/s ± 0% 191MB/s ± 0% -1.71% (p=0.008 n=5+5)
wuffs_deflate_decode_1k_part_init/clang11 224MB/s ± 0% 225MB/s ± 0% +0.87% (p=0.008 n=5+5)
wuffs_deflate_decode_10k_full_init/clang11 421MB/s ± 0% 401MB/s ± 0% -4.59% (p=0.008 n=5+5)
wuffs_deflate_decode_10k_part_init/clang11 432MB/s ± 0% 413MB/s ± 0% -4.49% (p=0.008 n=5+5)
wuffs_deflate_decode_100k_just_one_read/clang11 542MB/s ± 0% 518MB/s ± 0% -4.43% (p=0.008 n=5+5)
wuffs_deflate_decode_100k_many_big_reads/clang11 338MB/s ± 0% 325MB/s ± 0% -3.81% (p=0.008 n=5+5)
wuffs_deflate_decode_1k_full_init/gcc10 181MB/s ± 0% 185MB/s ± 0% +1.76% (p=0.008 n=5+5)
wuffs_deflate_decode_1k_part_init/gcc10 209MB/s ± 0% 212MB/s ± 0% +1.79% (p=0.008 n=5+5)
wuffs_deflate_decode_10k_full_init/gcc10 410MB/s ± 0% 407MB/s ± 0% -0.93% (p=0.008 n=5+5)
wuffs_deflate_decode_10k_part_init/gcc10 421MB/s ± 0% 418MB/s ± 0% -0.87% (p=0.008 n=5+5)
wuffs_deflate_decode_100k_just_one_read/gcc10 533MB/s ± 0% 533MB/s ± 0% ~ (p=0.548 n=5+5)
wuffs_deflate_decode_100k_many_big_reads/gcc10 336MB/s ± 0% 334MB/s ± 1% -0.67% (p=0.008 n=5+5)
wuffs_gzip_decode_10k/clang11 401MB/s ± 0% 398MB/s ± 0% -0.77% (p=0.008 n=5+5)
wuffs_gzip_decode_100k/clang11 505MB/s ± 0% 503MB/s ± 0% -0.46% (p=0.008 n=5+5)
wuffs_gzip_decode_10k/gcc10 403MB/s ± 0% 410MB/s ± 0% +1.90% (p=0.008 n=5+5)
wuffs_gzip_decode_100k/gcc10 522MB/s ± 0% 523MB/s ± 0% +0.10% (p=0.032 n=5+5)
wuffs_zlib_decode_10k/clang11 418MB/s ± 0% 417MB/s ± 1% ~ (p=0.310 n=5+5)
wuffs_zlib_decode_100k/clang11 530MB/s ± 0% 529MB/s ± 0% ~ (p=0.421 n=5+5)
wuffs_zlib_decode_10k/gcc10 428MB/s ± 0% 434MB/s ± 0% +1.50% (p=0.008 n=5+5)
wuffs_zlib_decode_100k/gcc10 551MB/s ± 0% 551MB/s ± 0% ~ (p=0.690 n=5+5)
Fixes #96
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index d00acc1..58c7c14 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -6893,6 +6893,7 @@
extern const char wuffs_bzip2__error__bad_checksum[];
extern const char wuffs_bzip2__error__bad_header[];
extern const char wuffs_bzip2__error__bad_number_of_sections[];
+extern const char wuffs_bzip2__error__truncated_input[];
extern const char wuffs_bzip2__error__unsupported_block_randomization[];
// ---------------- Public Consts
@@ -7018,6 +7019,7 @@
uint32_t f_code_lengths_bitmask;
uint32_t p_transform_io[1];
+ uint32_t p_do_transform_io[1];
uint32_t p_prepare_block[1];
uint32_t p_read_code_lengths[1];
uint32_t p_flush_slow[1];
@@ -7038,7 +7040,7 @@
uint32_t v_i;
uint64_t v_tag;
uint32_t v_final_checksum_want;
- } s_transform_io[1];
+ } s_do_transform_io[1];
struct {
uint32_t v_i;
uint32_t v_selector;
@@ -7581,6 +7583,7 @@
extern const char wuffs_deflate__error__inconsistent_stored_block_length[];
extern const char wuffs_deflate__error__missing_end_of_block_code[];
extern const char wuffs_deflate__error__no_huffman_codes[];
+extern const char wuffs_deflate__error__truncated_input[];
// ---------------- Public Consts
@@ -7695,6 +7698,7 @@
bool f_end_of_block;
uint32_t p_transform_io[1];
+ uint32_t p_do_transform_io[1];
uint32_t p_decode_blocks[1];
uint32_t p_decode_uncompressed[1];
uint32_t p_init_dynamic_huffman[1];
@@ -8512,6 +8516,7 @@
extern const char wuffs_gzip__error__bad_compression_method[];
extern const char wuffs_gzip__error__bad_encoding_flags[];
extern const char wuffs_gzip__error__bad_header[];
+extern const char wuffs_gzip__error__truncated_input[];
// ---------------- Public Consts
@@ -8616,6 +8621,7 @@
bool f_ignore_checksum;
uint32_t p_transform_io[1];
+ uint32_t p_do_transform_io[1];
} private_impl;
struct {
@@ -8628,7 +8634,7 @@
uint32_t v_decoded_length_got;
uint32_t v_checksum_want;
uint64_t scratch;
- } s_transform_io[1];
+ } s_do_transform_io[1];
} private_data;
#ifdef __cplusplus
@@ -9324,6 +9330,7 @@
extern const char wuffs_zlib__error__bad_compression_window_size[];
extern const char wuffs_zlib__error__bad_parity_check[];
extern const char wuffs_zlib__error__incorrect_dictionary[];
+extern const char wuffs_zlib__error__truncated_input[];
// ---------------- Public Consts
@@ -9446,6 +9453,7 @@
uint32_t f_dict_id_want;
uint32_t p_transform_io[1];
+ uint32_t p_do_transform_io[1];
} private_impl;
struct {
@@ -9456,7 +9464,7 @@
struct {
uint32_t v_checksum_got;
uint64_t scratch;
- } s_transform_io[1];
+ } s_do_transform_io[1];
} private_data;
#ifdef __cplusplus
@@ -24981,6 +24989,7 @@
const char wuffs_bzip2__error__bad_checksum[] = "#bzip2: bad checksum";
const char wuffs_bzip2__error__bad_header[] = "#bzip2: bad header";
const char wuffs_bzip2__error__bad_number_of_sections[] = "#bzip2: bad number of sections";
+const char wuffs_bzip2__error__truncated_input[] = "#bzip2: truncated input";
const char wuffs_bzip2__error__unsupported_block_randomization[] = "#bzip2: unsupported block randomization";
const char wuffs_bzip2__error__internal_error_inconsistent_huffman_decoder_state[] = "#bzip2: internal error: inconsistent Huffman decoder state";
@@ -25032,6 +25041,13 @@
// ---------------- Private Function Prototypes
static wuffs_base__status
+wuffs_bzip2__decoder__do_transform_io(
+ wuffs_bzip2__decoder* self,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf);
+
+static wuffs_base__status
wuffs_bzip2__decoder__prepare_block(
wuffs_bzip2__decoder* self,
wuffs_base__io_buffer* a_src);
@@ -25225,6 +25241,74 @@
self->private_impl.active_coroutine = 0;
wuffs_base__status status = wuffs_base__make_status(NULL);
+ wuffs_base__status v_status = wuffs_base__make_status(NULL);
+
+ const uint8_t* iop_a_src = NULL;
+ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src && a_src->data.ptr) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
+ }
+
+ uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
+ switch (coro_susp_point) {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+ while (true) {
+ {
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+ wuffs_base__status t_0 = wuffs_bzip2__decoder__do_transform_io(self, a_dst, a_src, a_workbuf);
+ v_status = t_0;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
+ }
+ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) {
+ status = wuffs_base__make_status(wuffs_bzip2__error__truncated_input);
+ goto exit;
+ }
+ status = v_status;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+ }
+
+ ok:
+ self->private_impl.p_transform_io[0] = 0;
+ goto exit;
+ }
+
+ goto suspend;
+ suspend:
+ self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
+
+ goto exit;
+ exit:
+ if (a_src && a_src->data.ptr) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+
+ if (wuffs_base__status__is_error(&status)) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ }
+ return status;
+}
+
+// -------- func bzip2.decoder.do_transform_io
+
+static wuffs_base__status
+wuffs_bzip2__decoder__do_transform_io(
+ wuffs_bzip2__decoder* self,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf) {
+ wuffs_base__status status = wuffs_base__make_status(NULL);
+
uint8_t v_c = 0;
uint32_t v_i = 0;
uint64_t v_tag = 0;
@@ -25242,11 +25326,11 @@
io2_a_src = io0_a_src + a_src->meta.wi;
}
- uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
+ uint32_t coro_susp_point = self->private_impl.p_do_transform_io[0];
if (coro_susp_point) {
- v_i = self->private_data.s_transform_io[0].v_i;
- v_tag = self->private_data.s_transform_io[0].v_tag;
- v_final_checksum_want = self->private_data.s_transform_io[0].v_final_checksum_want;
+ v_i = self->private_data.s_do_transform_io[0].v_i;
+ v_tag = self->private_data.s_do_transform_io[0].v_tag;
+ v_final_checksum_want = self->private_data.s_do_transform_io[0].v_final_checksum_want;
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
@@ -25435,17 +25519,16 @@
goto ok;
ok:
- self->private_impl.p_transform_io[0] = 0;
+ self->private_impl.p_do_transform_io[0] = 0;
goto exit;
}
goto suspend;
suspend:
- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
- self->private_data.s_transform_io[0].v_i = v_i;
- self->private_data.s_transform_io[0].v_tag = v_tag;
- self->private_data.s_transform_io[0].v_final_checksum_want = v_final_checksum_want;
+ self->private_impl.p_do_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+ self->private_data.s_do_transform_io[0].v_i = v_i;
+ self->private_data.s_do_transform_io[0].v_tag = v_tag;
+ self->private_data.s_do_transform_io[0].v_final_checksum_want = v_final_checksum_want;
goto exit;
exit:
@@ -25453,9 +25536,6 @@
a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
- if (wuffs_base__status__is_error(&status)) {
- self->private_impl.magic = WUFFS_BASE__DISABLED;
- }
return status;
}
@@ -28418,6 +28498,7 @@
const char wuffs_deflate__error__inconsistent_stored_block_length[] = "#deflate: inconsistent stored block length";
const char wuffs_deflate__error__missing_end_of_block_code[] = "#deflate: missing end-of-block code";
const char wuffs_deflate__error__no_huffman_codes[] = "#deflate: no Huffman codes";
+const char wuffs_deflate__error__truncated_input[] = "#deflate: truncated input";
const char wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state[] = "#deflate: internal error: inconsistent Huffman decoder state";
const char wuffs_deflate__error__internal_error_inconsistent_i_o[] = "#deflate: internal error: inconsistent I/O";
const char wuffs_deflate__error__internal_error_inconsistent_distance[] = "#deflate: internal error: inconsistent distance";
@@ -28493,6 +28574,13 @@
// ---------------- Private Function Prototypes
static wuffs_base__status
+wuffs_deflate__decoder__do_transform_io(
+ wuffs_deflate__decoder* self,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf);
+
+static wuffs_base__status
wuffs_deflate__decoder__decode_blocks(
wuffs_deflate__decoder* self,
wuffs_base__io_buffer* a_dst,
@@ -28735,6 +28823,74 @@
self->private_impl.active_coroutine = 0;
wuffs_base__status status = wuffs_base__make_status(NULL);
+ wuffs_base__status v_status = wuffs_base__make_status(NULL);
+
+ const uint8_t* iop_a_src = NULL;
+ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src && a_src->data.ptr) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
+ }
+
+ uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
+ switch (coro_susp_point) {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+ while (true) {
+ {
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+ wuffs_base__status t_0 = wuffs_deflate__decoder__do_transform_io(self, a_dst, a_src, a_workbuf);
+ v_status = t_0;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
+ }
+ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) {
+ status = wuffs_base__make_status(wuffs_deflate__error__truncated_input);
+ goto exit;
+ }
+ status = v_status;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+ }
+
+ ok:
+ self->private_impl.p_transform_io[0] = 0;
+ goto exit;
+ }
+
+ goto suspend;
+ suspend:
+ self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
+
+ goto exit;
+ exit:
+ if (a_src && a_src->data.ptr) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+
+ if (wuffs_base__status__is_error(&status)) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ }
+ return status;
+}
+
+// -------- func deflate.decoder.do_transform_io
+
+static wuffs_base__status
+wuffs_deflate__decoder__do_transform_io(
+ wuffs_deflate__decoder* self,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf) {
+ wuffs_base__status status = wuffs_base__make_status(NULL);
+
uint64_t v_mark = 0;
wuffs_base__status v_status = wuffs_base__make_status(NULL);
@@ -28752,7 +28908,7 @@
}
}
- uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
+ uint32_t coro_susp_point = self->private_impl.p_do_transform_io[0];
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
@@ -28790,14 +28946,13 @@
}
ok:
- self->private_impl.p_transform_io[0] = 0;
+ self->private_impl.p_do_transform_io[0] = 0;
goto exit;
}
goto suspend;
suspend:
- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
+ self->private_impl.p_do_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
goto exit;
exit:
@@ -28805,9 +28960,6 @@
a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
- if (wuffs_base__status__is_error(&status)) {
- self->private_impl.magic = WUFFS_BASE__DISABLED;
- }
return status;
}
@@ -33808,6 +33960,7 @@
const char wuffs_gzip__error__bad_compression_method[] = "#gzip: bad compression method";
const char wuffs_gzip__error__bad_encoding_flags[] = "#gzip: bad encoding flags";
const char wuffs_gzip__error__bad_header[] = "#gzip: bad header";
+const char wuffs_gzip__error__truncated_input[] = "#gzip: truncated input";
// ---------------- Private Consts
@@ -33815,6 +33968,13 @@
// ---------------- Private Function Prototypes
+static wuffs_base__status
+wuffs_gzip__decoder__do_transform_io(
+ wuffs_gzip__decoder* self,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf);
+
// ---------------- VTables
const wuffs_base__io_transformer__func_ptrs
@@ -33979,6 +34139,74 @@
self->private_impl.active_coroutine = 0;
wuffs_base__status status = wuffs_base__make_status(NULL);
+ wuffs_base__status v_status = wuffs_base__make_status(NULL);
+
+ const uint8_t* iop_a_src = NULL;
+ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src && a_src->data.ptr) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
+ }
+
+ uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
+ switch (coro_susp_point) {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+ while (true) {
+ {
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+ wuffs_base__status t_0 = wuffs_gzip__decoder__do_transform_io(self, a_dst, a_src, a_workbuf);
+ v_status = t_0;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
+ }
+ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) {
+ status = wuffs_base__make_status(wuffs_gzip__error__truncated_input);
+ goto exit;
+ }
+ status = v_status;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+ }
+
+ ok:
+ self->private_impl.p_transform_io[0] = 0;
+ goto exit;
+ }
+
+ goto suspend;
+ suspend:
+ self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
+
+ goto exit;
+ exit:
+ if (a_src && a_src->data.ptr) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+
+ if (wuffs_base__status__is_error(&status)) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ }
+ return status;
+}
+
+// -------- func gzip.decoder.do_transform_io
+
+static wuffs_base__status
+wuffs_gzip__decoder__do_transform_io(
+ wuffs_gzip__decoder* self,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf) {
+ wuffs_base__status status = wuffs_base__make_status(NULL);
+
uint8_t v_c = 0;
uint8_t v_flags = 0;
uint16_t v_xlen = 0;
@@ -34013,12 +34241,12 @@
io2_a_src = io0_a_src + a_src->meta.wi;
}
- uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
+ uint32_t coro_susp_point = self->private_impl.p_do_transform_io[0];
if (coro_susp_point) {
- v_flags = self->private_data.s_transform_io[0].v_flags;
- v_checksum_got = self->private_data.s_transform_io[0].v_checksum_got;
- v_decoded_length_got = self->private_data.s_transform_io[0].v_decoded_length_got;
- v_checksum_want = self->private_data.s_transform_io[0].v_checksum_want;
+ v_flags = self->private_data.s_do_transform_io[0].v_flags;
+ v_checksum_got = self->private_data.s_do_transform_io[0].v_checksum_got;
+ v_decoded_length_got = self->private_data.s_do_transform_io[0].v_decoded_length_got;
+ v_checksum_want = self->private_data.s_do_transform_io[0].v_checksum_want;
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
@@ -34071,15 +34299,15 @@
uint8_t t_3 = *iop_a_src++;
v_flags = t_3;
}
- self->private_data.s_transform_io[0].scratch = 6;
+ self->private_data.s_do_transform_io[0].scratch = 6;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
- if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
- self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
+ if (self->private_data.s_do_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
+ self->private_data.s_do_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
iop_a_src = io2_a_src;
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- iop_a_src += self->private_data.s_transform_io[0].scratch;
+ iop_a_src += self->private_data.s_do_transform_io[0].scratch;
if ((v_flags & 4) != 0) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
@@ -34088,14 +34316,14 @@
t_4 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
iop_a_src += 2;
} else {
- self->private_data.s_transform_io[0].scratch = 0;
+ self->private_data.s_do_transform_io[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
while (true) {
if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
+ uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch;
uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
*scratch <<= 8;
*scratch >>= 8;
@@ -34110,15 +34338,15 @@
}
v_xlen = t_4;
}
- self->private_data.s_transform_io[0].scratch = ((uint32_t)(v_xlen));
+ self->private_data.s_do_transform_io[0].scratch = ((uint32_t)(v_xlen));
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
- if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
- self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
+ if (self->private_data.s_do_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
+ self->private_data.s_do_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
iop_a_src = io2_a_src;
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- iop_a_src += self->private_data.s_transform_io[0].scratch;
+ iop_a_src += self->private_data.s_do_transform_io[0].scratch;
}
if ((v_flags & 8) != 0) {
while (true) {
@@ -34155,15 +34383,15 @@
label__1__break:;
}
if ((v_flags & 2) != 0) {
- self->private_data.s_transform_io[0].scratch = 2;
+ self->private_data.s_do_transform_io[0].scratch = 2;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
- if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
- self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
+ if (self->private_data.s_do_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
+ self->private_data.s_do_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
iop_a_src = io2_a_src;
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- iop_a_src += self->private_data.s_transform_io[0].scratch;
+ iop_a_src += self->private_data.s_do_transform_io[0].scratch;
}
if ((v_flags & 224) != 0) {
status = wuffs_base__make_status(wuffs_gzip__error__bad_encoding_flags);
@@ -34205,14 +34433,14 @@
t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
iop_a_src += 4;
} else {
- self->private_data.s_transform_io[0].scratch = 0;
+ self->private_data.s_do_transform_io[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
while (true) {
if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
+ uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch;
uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56));
*scratch <<= 8;
*scratch >>= 8;
@@ -34234,14 +34462,14 @@
t_9 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
iop_a_src += 4;
} else {
- self->private_data.s_transform_io[0].scratch = 0;
+ self->private_data.s_do_transform_io[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
while (true) {
if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
+ uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch;
uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56));
*scratch <<= 8;
*scratch >>= 8;
@@ -34262,18 +34490,17 @@
}
ok:
- self->private_impl.p_transform_io[0] = 0;
+ self->private_impl.p_do_transform_io[0] = 0;
goto exit;
}
goto suspend;
suspend:
- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
- self->private_data.s_transform_io[0].v_flags = v_flags;
- self->private_data.s_transform_io[0].v_checksum_got = v_checksum_got;
- self->private_data.s_transform_io[0].v_decoded_length_got = v_decoded_length_got;
- self->private_data.s_transform_io[0].v_checksum_want = v_checksum_want;
+ self->private_impl.p_do_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+ self->private_data.s_do_transform_io[0].v_flags = v_flags;
+ self->private_data.s_do_transform_io[0].v_checksum_got = v_checksum_got;
+ self->private_data.s_do_transform_io[0].v_decoded_length_got = v_decoded_length_got;
+ self->private_data.s_do_transform_io[0].v_checksum_want = v_checksum_want;
goto exit;
exit:
@@ -34284,9 +34511,6 @@
a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
- if (wuffs_base__status__is_error(&status)) {
- self->private_impl.magic = WUFFS_BASE__DISABLED;
- }
return status;
}
@@ -37339,6 +37563,7 @@
const char wuffs_zlib__error__bad_compression_window_size[] = "#zlib: bad compression window size";
const char wuffs_zlib__error__bad_parity_check[] = "#zlib: bad parity check";
const char wuffs_zlib__error__incorrect_dictionary[] = "#zlib: incorrect dictionary";
+const char wuffs_zlib__error__truncated_input[] = "#zlib: truncated input";
// ---------------- Private Consts
@@ -37350,6 +37575,13 @@
// ---------------- Private Function Prototypes
+static wuffs_base__status
+wuffs_zlib__decoder__do_transform_io(
+ wuffs_zlib__decoder* self,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf);
+
// ---------------- VTables
const wuffs_base__io_transformer__func_ptrs
@@ -37567,6 +37799,74 @@
self->private_impl.active_coroutine = 0;
wuffs_base__status status = wuffs_base__make_status(NULL);
+ wuffs_base__status v_status = wuffs_base__make_status(NULL);
+
+ const uint8_t* iop_a_src = NULL;
+ const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src && a_src->data.ptr) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
+ }
+
+ uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
+ switch (coro_susp_point) {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+ while (true) {
+ {
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+ wuffs_base__status t_0 = wuffs_zlib__decoder__do_transform_io(self, a_dst, a_src, a_workbuf);
+ v_status = t_0;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
+ }
+ if ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed)) {
+ status = wuffs_base__make_status(wuffs_zlib__error__truncated_input);
+ goto exit;
+ }
+ status = v_status;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+ }
+
+ ok:
+ self->private_impl.p_transform_io[0] = 0;
+ goto exit;
+ }
+
+ goto suspend;
+ suspend:
+ self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
+
+ goto exit;
+ exit:
+ if (a_src && a_src->data.ptr) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+
+ if (wuffs_base__status__is_error(&status)) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ }
+ return status;
+}
+
+// -------- func zlib.decoder.do_transform_io
+
+static wuffs_base__status
+wuffs_zlib__decoder__do_transform_io(
+ wuffs_zlib__decoder* self,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf) {
+ wuffs_base__status status = wuffs_base__make_status(NULL);
+
uint16_t v_x = 0;
uint32_t v_checksum_got = 0;
wuffs_base__status v_status = wuffs_base__make_status(NULL);
@@ -37597,9 +37897,9 @@
io2_a_src = io0_a_src + a_src->meta.wi;
}
- uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
+ uint32_t coro_susp_point = self->private_impl.p_do_transform_io[0];
if (coro_susp_point) {
- v_checksum_got = self->private_data.s_transform_io[0].v_checksum_got;
+ v_checksum_got = self->private_data.s_do_transform_io[0].v_checksum_got;
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
@@ -37616,14 +37916,14 @@
t_0 = wuffs_base__peek_u16be__no_bounds_check(iop_a_src);
iop_a_src += 2;
} else {
- self->private_data.s_transform_io[0].scratch = 0;
+ self->private_data.s_do_transform_io[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
while (true) {
if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
+ uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch;
uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
*scratch >>= 8;
*scratch <<= 8;
@@ -37660,14 +37960,14 @@
t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
iop_a_src += 4;
} else {
- self->private_data.s_transform_io[0].scratch = 0;
+ self->private_data.s_do_transform_io[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
while (true) {
if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
+ uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch;
uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
*scratch >>= 8;
*scratch <<= 8;
@@ -37733,14 +38033,14 @@
t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
iop_a_src += 4;
} else {
- self->private_data.s_transform_io[0].scratch = 0;
+ self->private_data.s_do_transform_io[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
while (true) {
if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
goto suspend;
}
- uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
+ uint64_t* scratch = &self->private_data.s_do_transform_io[0].scratch;
uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
*scratch >>= 8;
*scratch <<= 8;
@@ -37762,15 +38062,14 @@
}
ok:
- self->private_impl.p_transform_io[0] = 0;
+ self->private_impl.p_do_transform_io[0] = 0;
goto exit;
}
goto suspend;
suspend:
- self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
- self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
- self->private_data.s_transform_io[0].v_checksum_got = v_checksum_got;
+ self->private_impl.p_do_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+ self->private_data.s_do_transform_io[0].v_checksum_got = v_checksum_got;
goto exit;
exit:
@@ -37781,9 +38080,6 @@
a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
- if (wuffs_base__status__is_error(&status)) {
- self->private_impl.magic = WUFFS_BASE__DISABLED;
- }
return status;
}
diff --git a/std/bzip2/decode_bzip2.wuffs b/std/bzip2/decode_bzip2.wuffs
index 19f670f..4bd3e92 100644
--- a/std/bzip2/decode_bzip2.wuffs
+++ b/std/bzip2/decode_bzip2.wuffs
@@ -19,6 +19,7 @@
pub status "#bad checksum"
pub status "#bad header"
pub status "#bad number of sections"
+pub status "#truncated input"
pub status "#unsupported block randomization"
pri status "#internal error: inconsistent Huffman decoder state"
@@ -121,6 +122,18 @@
}
pub func decoder.transform_io?(dst: base.io_writer, src: base.io_reader, workbuf: slice base.u8) {
+ var status : base.status
+
+ while true {
+ status =? this.do_transform_io?(dst: args.dst, src: args.src, workbuf: args.workbuf)
+ if (status == base."$short read") and args.src.is_closed() {
+ return "#truncated input"
+ }
+ yield? status
+ } endwhile
+}
+
+pri func decoder.do_transform_io?(dst: base.io_writer, src: base.io_reader, workbuf: slice base.u8) {
var c : base.u8
var i : base.u32
var tag : base.u64
diff --git a/std/deflate/decode_deflate.wuffs b/std/deflate/decode_deflate.wuffs
index 947f4f2..188b0ce 100644
--- a/std/deflate/decode_deflate.wuffs
+++ b/std/deflate/decode_deflate.wuffs
@@ -25,6 +25,7 @@
pub status "#inconsistent stored block length"
pub status "#missing end-of-block code"
pub status "#no Huffman codes"
+pub status "#truncated input"
pri status "#internal error: inconsistent Huffman decoder state"
pri status "#internal error: inconsistent I/O"
@@ -208,6 +209,18 @@
}
pub func decoder.transform_io?(dst: base.io_writer, src: base.io_reader, workbuf: slice base.u8) {
+ var status : base.status
+
+ while true {
+ status =? this.do_transform_io?(dst: args.dst, src: args.src, workbuf: args.workbuf)
+ if (status == base."$short read") and args.src.is_closed() {
+ return "#truncated input"
+ }
+ yield? status
+ } endwhile
+}
+
+pri func decoder.do_transform_io?(dst: base.io_writer, src: base.io_reader, workbuf: slice base.u8) {
var mark : base.u64
var status : base.status
diff --git a/std/gzip/decode_gzip.wuffs b/std/gzip/decode_gzip.wuffs
index f66e63d..699975b 100644
--- a/std/gzip/decode_gzip.wuffs
+++ b/std/gzip/decode_gzip.wuffs
@@ -19,6 +19,7 @@
pub status "#bad compression method"
pub status "#bad encoding flags"
pub status "#bad header"
+pub status "#truncated input"
// TODO: reference deflate.DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE.
pub const DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE : base.u64 = 1
@@ -45,6 +46,18 @@
}
pub func decoder.transform_io?(dst: base.io_writer, src: base.io_reader, workbuf: slice base.u8) {
+ var status : base.status
+
+ while true {
+ status =? this.do_transform_io?(dst: args.dst, src: args.src, workbuf: args.workbuf)
+ if (status == base."$short read") and args.src.is_closed() {
+ return "#truncated input"
+ }
+ yield? status
+ } endwhile
+}
+
+pri func decoder.do_transform_io?(dst: base.io_writer, src: base.io_reader, workbuf: slice base.u8) {
var c : base.u8
var flags : base.u8
var xlen : base.u16
diff --git a/std/zlib/decode_zlib.wuffs b/std/zlib/decode_zlib.wuffs
index b328588..cf06113 100644
--- a/std/zlib/decode_zlib.wuffs
+++ b/std/zlib/decode_zlib.wuffs
@@ -22,6 +22,7 @@
pub status "#bad compression window size"
pub status "#bad parity check"
pub status "#incorrect dictionary"
+pub status "#truncated input"
// TODO: reference deflate.DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE.
pub const DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE : base.u64 = 1
@@ -81,6 +82,18 @@
}
pub func decoder.transform_io?(dst: base.io_writer, src: base.io_reader, workbuf: slice base.u8) {
+ var status : base.status
+
+ while true {
+ status =? this.do_transform_io?(dst: args.dst, src: args.src, workbuf: args.workbuf)
+ if (status == base."$short read") and args.src.is_closed() {
+ return "#truncated input"
+ }
+ yield? status
+ } endwhile
+}
+
+pri func decoder.do_transform_io?(dst: base.io_writer, src: base.io_reader, workbuf: slice base.u8) {
var x : base.u16
var checksum_got : base.u32
var status : base.status
diff --git a/test/c/std/bzip2.c b/test/c/std/bzip2.c
index 8fe938a..380496b 100644
--- a/test/c/std/bzip2.c
+++ b/test/c/std/bzip2.c
@@ -110,6 +110,36 @@
}
const char* //
+test_wuffs_bzip2_decode_truncated_input() {
+ CHECK_FOCUS(__func__);
+
+ wuffs_base__io_buffer have = wuffs_base__ptr_u8__writer(g_have_array_u8, 1);
+ wuffs_base__io_buffer src =
+ wuffs_base__ptr_u8__reader(g_src_array_u8, 0, false);
+ wuffs_bzip2__decoder dec;
+ CHECK_STATUS("initialize",
+ wuffs_bzip2__decoder__initialize(
+ &dec, sizeof dec, WUFFS_VERSION,
+ WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
+
+ wuffs_base__status status =
+ wuffs_bzip2__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_base__suspension__short_read) {
+ RETURN_FAIL("closed=false: have \"%s\", want \"%s\"", status.repr,
+ wuffs_base__suspension__short_read);
+ }
+
+ src.meta.closed = true;
+ status =
+ wuffs_bzip2__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_bzip2__error__truncated_input) {
+ RETURN_FAIL("closed=true: have \"%s\", want \"%s\"", status.repr,
+ wuffs_bzip2__error__truncated_input);
+ }
+ return NULL;
+}
+
+const char* //
wuffs_bzip2_decode(wuffs_base__io_buffer* dst,
wuffs_base__io_buffer* src,
uint32_t wuffs_initialize_flags,
@@ -262,6 +292,7 @@
test_wuffs_bzip2_decode_interface,
test_wuffs_bzip2_decode_midsummer,
test_wuffs_bzip2_decode_pi,
+ test_wuffs_bzip2_decode_truncated_input,
#ifdef WUFFS_MIMIC
diff --git a/test/c/std/deflate.c b/test/c/std/deflate.c
index a6d381a..de2dff6 100644
--- a/test/c/std/deflate.c
+++ b/test/c/std/deflate.c
@@ -167,6 +167,36 @@
}
const char* //
+test_wuffs_deflate_decode_truncated_input() {
+ CHECK_FOCUS(__func__);
+
+ wuffs_base__io_buffer have = wuffs_base__ptr_u8__writer(g_have_array_u8, 1);
+ wuffs_base__io_buffer src =
+ wuffs_base__ptr_u8__reader(g_src_array_u8, 0, false);
+ wuffs_deflate__decoder dec;
+ CHECK_STATUS("initialize",
+ wuffs_deflate__decoder__initialize(
+ &dec, sizeof dec, WUFFS_VERSION,
+ WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
+
+ wuffs_base__status status =
+ wuffs_deflate__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_base__suspension__short_read) {
+ RETURN_FAIL("closed=false: have \"%s\", want \"%s\"", status.repr,
+ wuffs_base__suspension__short_read);
+ }
+
+ src.meta.closed = true;
+ status =
+ wuffs_deflate__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_deflate__error__truncated_input) {
+ RETURN_FAIL("closed=true: have \"%s\", want \"%s\"", status.repr,
+ wuffs_deflate__error__truncated_input);
+ }
+ return NULL;
+}
+
+const char* //
wuffs_deflate_decode(wuffs_base__io_buffer* dst,
wuffs_base__io_buffer* src,
uint32_t wuffs_initialize_flags,
@@ -903,6 +933,7 @@
test_wuffs_deflate_decode_romeo,
test_wuffs_deflate_decode_romeo_fixed,
test_wuffs_deflate_decode_split_src,
+ test_wuffs_deflate_decode_truncated_input,
test_wuffs_deflate_history_full,
test_wuffs_deflate_history_partial,
test_wuffs_deflate_table_redirect,
diff --git a/test/c/std/gzip.c b/test/c/std/gzip.c
index a7072ab..f3620d2 100644
--- a/test/c/std/gzip.c
+++ b/test/c/std/gzip.c
@@ -97,6 +97,36 @@
}
const char* //
+test_wuffs_gzip_decode_truncated_input() {
+ CHECK_FOCUS(__func__);
+
+ wuffs_base__io_buffer have = wuffs_base__ptr_u8__writer(g_have_array_u8, 1);
+ wuffs_base__io_buffer src =
+ wuffs_base__ptr_u8__reader(g_src_array_u8, 0, false);
+ wuffs_gzip__decoder dec;
+ CHECK_STATUS("initialize",
+ wuffs_gzip__decoder__initialize(
+ &dec, sizeof dec, WUFFS_VERSION,
+ WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
+
+ wuffs_base__status status =
+ wuffs_gzip__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_base__suspension__short_read) {
+ RETURN_FAIL("closed=false: have \"%s\", want \"%s\"", status.repr,
+ wuffs_base__suspension__short_read);
+ }
+
+ src.meta.closed = true;
+ status =
+ wuffs_gzip__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_gzip__error__truncated_input) {
+ RETURN_FAIL("closed=true: have \"%s\", want \"%s\"", status.repr,
+ wuffs_gzip__error__truncated_input);
+ }
+ return NULL;
+}
+
+const char* //
wuffs_gzip_decode(wuffs_base__io_buffer* dst,
wuffs_base__io_buffer* src,
uint32_t wuffs_initialize_flags,
@@ -255,6 +285,7 @@
// Decode 5 source bytes at a time. Compact every 15 source bytes.
for (size_t i = 0; i < src.data.len; i += 5) {
src.meta.wi = i;
+ src.meta.closed = false;
wuffs_base__status status =
wuffs_gzip__decoder__transform_io(&dec, &dst, &src, g_work_slice_u8);
if (status.repr != wuffs_base__suspension__short_read) {
@@ -361,6 +392,7 @@
test_wuffs_gzip_decode_interface,
test_wuffs_gzip_decode_midsummer,
test_wuffs_gzip_decode_pi,
+ test_wuffs_gzip_decode_truncated_input,
#ifdef WUFFS_MIMIC
diff --git a/test/c/std/zlib.c b/test/c/std/zlib.c
index d7fd607..4c6b775 100644
--- a/test/c/std/zlib.c
+++ b/test/c/std/zlib.c
@@ -113,6 +113,36 @@
}
const char* //
+test_wuffs_zlib_decode_truncated_input() {
+ CHECK_FOCUS(__func__);
+
+ wuffs_base__io_buffer have = wuffs_base__ptr_u8__writer(g_have_array_u8, 1);
+ wuffs_base__io_buffer src =
+ wuffs_base__ptr_u8__reader(g_src_array_u8, 0, false);
+ wuffs_zlib__decoder dec;
+ CHECK_STATUS("initialize",
+ wuffs_zlib__decoder__initialize(
+ &dec, sizeof dec, WUFFS_VERSION,
+ WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
+
+ wuffs_base__status status =
+ wuffs_zlib__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_base__suspension__short_read) {
+ RETURN_FAIL("closed=false: have \"%s\", want \"%s\"", status.repr,
+ wuffs_base__suspension__short_read);
+ }
+
+ src.meta.closed = true;
+ status =
+ wuffs_zlib__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_zlib__error__truncated_input) {
+ RETURN_FAIL("closed=true: have \"%s\", want \"%s\"", status.repr,
+ wuffs_zlib__error__truncated_input);
+ }
+ return NULL;
+}
+
+const char* //
wuffs_raw_deflate_decode(wuffs_base__io_buffer* dst,
wuffs_base__io_buffer* src,
uint32_t wuffs_initialize_flags,
@@ -426,6 +456,7 @@
test_wuffs_zlib_decode_pi,
test_wuffs_zlib_decode_raw_deflate_romeo,
test_wuffs_zlib_decode_sheep,
+ test_wuffs_zlib_decode_truncated_input,
#ifdef WUFFS_MIMIC