|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
RFC 1952 gzip member decoder over the vendored miniz tinfl core. More...
#include "unarch_gzip.h"#include <string.h>#include "miniz.h"#include "ra8_attributes.h"#include "ra8_check.h"Go to the source code of this file.
Data Structures | |
| struct | gz_src_t |
| Cursor-tracked exact-read byte source with a running header CRC. More... | |
| struct | gz_inflate_t |
| Loop-carried state of the windowed DEFLATE inflation. More... | |
Enumerations | |
| enum | gz_grammar_t : uint32_t { k_gz_id1 = 0x1FU , k_gz_id2 = 0x8BU , k_gz_cm_deflate = 8U , k_gz_flg_fhcrc = 0x02U , k_gz_flg_fextra = 0x04U , k_gz_flg_fname = 0x08U , k_gz_flg_fcomment = 0x10U , k_gz_flg_reserved = 0xE0U , k_gz_hdr_fixed = 10U , k_gz_xlen_bytes = 2U , k_gz_fhcrc_bytes = 2U , k_gz_trailer_len = 8U , k_gz_idx_id1 = 0U , k_gz_idx_id2 = 1U , k_gz_idx_cm = 2U , k_gz_idx_flg = 3U , k_gz_in_chunk = 512U , k_gz_out_window = 4096U , k_gz_shift_byte = 8U , k_gz_crc16_mask = 0xFFFFU , k_gz_isize_mask = 0xFFFFFFFFU } |
| RFC 1952 constants and this decoder's loop windows. More... | |
Functions | |
| static ra8_err_t | internal_src_take (gz_src_t *s, uint8_t *dst, size_t n) |
Consume exactly n bytes from the source into dst. | |
| static ra8_err_t | internal_skip_string (gz_src_t *s) |
| Skip a NUL-terminated header string (FNAME / FCOMMENT), bounded. | |
| static ra8_err_t | internal_skip_fextra (gz_src_t *s) |
| Skip the FEXTRA subfield block (RFC 1952 XLEN + XLEN bytes), bounded. | |
| static ra8_err_t | internal_parse_header (gz_src_t *s) |
| Parse the whole RFC 1952 header, leaving the cursor at the data. | |
| static ra8_err_t | internal_inflate_pass (gz_inflate_t *st) |
| Run one refill + inflate pass of the DEFLATE loop. | |
| static ra8_err_t | internal_verify_trailer (const gz_inflate_t *st) |
| Verify the gzip trailer against the produced payload. | |
| bool | unarch_gzip_magic (const uint8_t *sig, size_t sig_len) |
Whether sig begins with the gzip member magic (1F 8B). | |
| ra8_err_t | unarch_gzip_unwrap (unarch_read_fn read, void *ctx, uint64_t size, uint8_t *out, size_t out_cap, const ra8_decomp_limits_t *limits, size_t *out_len) |
| Decode one whole gzip member from a read seam into a caller arena. | |
Variables | |
| static tinfl_decompressor | s_gz_inflator |
| The single-client tinfl state (too large for a task stack). | |
RFC 1952 gzip member decoder over the vendored miniz tinfl core.
See unarch_gzip.h for the contract. The TU is organised as a small cursor-tracked byte source over the shared read seam (exact reads, running CRC32 for the optional FHCRC header check), a fail-closed header parser, a windowed tinfl_decompress loop that charges the unified decompression budget every pass, and a trailer verifier. The DEFLATE decompressor state (~11 KiB) lives in one module-static arena rather than the stack (single-client, zero heap – the same idiom as the XZ pool), so the reader task's stack budget is untouched.
Definition in file unarch_gzip.c.
| enum gz_grammar_t : uint32_t |
RFC 1952 constants and this decoder's loop windows.
Definition at line 42 of file unarch_gzip.c.
|
static |
Run one refill + inflate pass of the DEFLATE loop.
Charges one iteration, refills the input window when drained, inflates into a bounded output window, folds the produced bytes into the payload CRC, and charges the output budget. Truncation (input exhausted before stream end), corruption, and an overrun arena each fail closed.
| [in,out] | st | Inflation state. |
| k_ra8_ok | Pass complete; check st->done. |
| k_ra8_err_no_mem | Arena full with the stream open. |
| k_ra8_err_validation_failed | Truncated / corrupt stream. |
| k_ra8_err_decomp_* | A policy bound was breached. |
Definition at line 314 of file unarch_gzip.c.
References gz_inflate_t::budget, gz_inflate_t::crc, gz_inflate_t::done, internal_src_take(), k_gz_out_window, k_ra8_err_no_mem, k_ra8_err_validation_failed, k_ra8_ok, gz_inflate_t::out, gz_inflate_t::out_cap, gz_src_t::pos, ra8_decomp_budget_charge_iter(), ra8_decomp_budget_charge_output(), s_gz_inflator, gz_src_t::size, gz_inflate_t::src, gz_inflate_t::total, gz_inflate_t::win, gz_inflate_t::win_len, and gz_inflate_t::win_ofs.
Referenced by unarch_gzip_unwrap().
Parse the whole RFC 1952 header, leaving the cursor at the data.
Fixed fields first (magic, method, flags – reserved bits rejected), then the optional fields in wire order: FEXTRA (bounded by its own length field), FNAME, FCOMMENT (bounded strings), and FHCRC (verified against the running CRC of every header byte before it).
| [in,out] | s | Byte source at offset 0. |
| k_ra8_ok | Header consumed; cursor at DEFLATE. |
| k_ra8_err_not_supported | Bad magic / method / reserved bits. |
| k_ra8_err_checksum_mismatch | FHCRC verification failed. |
| k_ra8_err_validation_failed | Truncated or over-long fields. |
s was bound with pos == 0 and CRC tracking on. Definition at line 215 of file unarch_gzip.c.
References gz_src_t::crc, internal_skip_fextra(), internal_skip_string(), internal_src_take(), k_gz_cm_deflate, k_gz_crc16_mask, k_gz_fhcrc_bytes, k_gz_flg_fcomment, k_gz_flg_fextra, k_gz_flg_fhcrc, k_gz_flg_fname, k_gz_flg_reserved, k_gz_hdr_fixed, k_gz_id1, k_gz_id2, k_gz_idx_cm, k_gz_idx_flg, k_gz_idx_id1, k_gz_idx_id2, k_gz_shift_byte, k_ra8_err_checksum_mismatch, k_ra8_err_not_supported, k_ra8_ok, and gz_src_t::track_crc.
Referenced by unarch_gzip_unwrap().
Skip the FEXTRA subfield block (RFC 1952 XLEN + XLEN bytes), bounded.
Reads the 2-byte little-endian XLEN, then consumes exactly that many bytes in k_gz_in_chunk-sized pieces. XLEN is at most 65535, so the loop is statically bounded.
| [in,out] | s | Byte source positioned at the FEXTRA XLEN field. |
| k_ra8_ok | XLEN and its payload consumed. |
| k_ra8_err_validation_failed | XLEN or the subfield ran past the member. |
s was bound to a live reader. Definition at line 173 of file unarch_gzip.c.
References internal_src_take(), k_gz_in_chunk, k_gz_shift_byte, k_gz_xlen_bytes, and k_ra8_ok.
Referenced by internal_parse_header().
Skip a NUL-terminated header string (FNAME / FCOMMENT), bounded.
Consumes bytes until the terminator; a string longer than k_unarch_gzip_str_max or an unterminated one (EOF first) rejects the member.
| [in,out] | s | Byte source positioned at the string start. |
| k_ra8_ok | Terminator consumed. |
| k_ra8_err_validation_failed | Over-long or unterminated string. |
s was bound to a live reader. Definition at line 141 of file unarch_gzip.c.
References internal_src_take(), k_ra8_err_validation_failed, k_ra8_ok, and k_unarch_gzip_str_max.
Referenced by internal_parse_header().
Consume exactly n bytes from the source into dst.
A short read (EOF under the parser) fails closed; consumed bytes advance the cursor and, while tracking, the running CRC.
| [in,out] | s | Byte source. |
| [out] | dst | Destination (n writable bytes). |
| [in] | n | Bytes required. |
| k_ra8_ok | Bytes consumed. |
| k_ra8_err_validation_failed | Truncated member. |
s was bound to a live reader. dst holds n writable bytes. n. Definition at line 108 of file unarch_gzip.c.
References gz_src_t::crc, gz_src_t::ctx, k_ra8_err_validation_failed, k_ra8_ok, gz_src_t::pos, gz_src_t::read, gz_src_t::size, and gz_src_t::track_crc.
Referenced by internal_inflate_pass(), internal_parse_header(), internal_skip_fextra(), and internal_skip_string().
|
static |
Verify the gzip trailer against the produced payload.
The trailer starts at the first unconsumed input byte: win_len - win_ofs leftover window bytes plus whatever the source still holds. CRC32 and ISIZE must both match, and nothing may follow the trailer.
| [in] | st | The completed inflation state. |
| k_ra8_ok | Trailer verified, member ends cleanly. |
| k_ra8_err_checksum_mismatch | CRC32 or ISIZE mismatch. |
| k_ra8_err_validation_failed | Truncated trailer or trailing bytes. |
Definition at line 391 of file unarch_gzip.c.
References gz_inflate_t::crc, gz_src_t::ctx, k_gz_isize_mask, k_gz_shift_byte, k_gz_trailer_len, k_ra8_err_checksum_mismatch, k_ra8_err_validation_failed, k_ra8_ok, gz_src_t::pos, gz_src_t::read, gz_src_t::size, gz_inflate_t::src, gz_inflate_t::total, gz_inflate_t::win_len, and gz_inflate_t::win_ofs.
Referenced by unarch_gzip_unwrap().
|
nodiscard |
Whether sig begins with the gzip member magic (1F 8B).
Pure signature probe so open paths can route a wrapped archive without constructing a decoder.
| [in] | sig | Leading archive bytes (may be NULL). |
| [in] | sig_len | Readable length of sig in bytes. |
| true | Both magic bytes match. |
| false | sig is NULL, too short, or not gzip. |
sig holds sig_len readable bytes when non-NULL. sig_len is the true readable length (untrusted values are safe). Definition at line 422 of file unarch_gzip.c.
References k_gz_id1, k_gz_id2, k_gz_idx_id1, k_gz_idx_id2, and k_unarch_gzip_sig_len.
Referenced by comic_open_wrapped(), and internal_open_unwrapped().
|
nodiscard |
Decode one whole gzip member from a read seam into a caller arena.
Parses the RFC 1952 header, inflates the DEFLATE stream in bounded passes charged against limits, and verifies the trailer (payload CRC32 + ISIZE). Fail-closed on everything else: a non-gzip or non-DEFLATE header, reserved flag bits, oversized name/comment fields, a failed header or payload checksum, truncation, corruption, output overrun, a policy breach, and trailing bytes after the member.
| [in] | read | Byte reader over the gzip member (non-NULL). |
| [in] | ctx | Context passed to read. |
| [in] | size | Member length in bytes (> 0). |
| [out] | out | Destination arena (non-NULL, out_cap bytes). |
| [in] | out_cap | Capacity of out in bytes (> 0). |
| [in] | limits | Policy to enforce, or NULL for the default. |
| [out] | out_len | Receives the decoded byte count (non-NULL). |
| k_ra8_ok | Member decoded and verified. |
| k_ra8_err_null_ptr | A required pointer was NULL. |
| k_ra8_err_invalid_size | size or out_cap is 0. |
| k_ra8_err_invalid_arg | limits has a zero field. |
| k_ra8_err_not_supported | Not gzip, not DEFLATE, or reserved flag bits set. |
| k_ra8_err_no_mem | out is too small for the member. |
| k_ra8_err_checksum_mismatch | Header FHCRC, payload CRC32, or ISIZE verification failed. |
| k_ra8_err_validation_failed | Truncated / corrupt stream, oversized header field, or trailing bytes after the member. |
| k_ra8_err_decomp_output_cap | Output exceeds the policy cap. |
| k_ra8_err_decomp_ratio | Output breached the ratio bound. |
| k_ra8_err_decomp_iterations | The decode loop budget ran out. |
read serves offsets [0, size) of the member. Definition at line 437 of file unarch_gzip.c.
References gz_inflate_t::budget, gz_inflate_t::crc, gz_inflate_t::done, internal_inflate_pass(), internal_parse_header(), internal_verify_trailer(), k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, gz_inflate_t::out, gz_inflate_t::out_cap, RA8_CHECK_NULL_PTR, ra8_decomp_budget_init(), ra8_log_error, s_gz_inflator, gz_inflate_t::src, and gz_inflate_t::total.
Referenced by internal_unwrap().
|
static |
The single-client tinfl state (too large for a task stack).
Definition at line 88 of file unarch_gzip.c.
Referenced by internal_inflate_pass(), and unarch_gzip_unwrap().