24typedef enum : uint16_t {
36typedef enum : uint32_t {
47typedef enum : uint8_t {
103 while ((index < length) && ((field[index] == (uint8_t)
' ') || (field[index] == (uint8_t)
'\0'))) {
108 for (; (index < length) && (field[index] != (uint8_t)
'\0') && (field[index] != (uint8_t)
' ');
110 if ((field[index] < (uint8_t)
'0') || (field[index] > (uint8_t)
'7') ||
111 (value > (UINT64_MAX >> 3U))) {
114 const uint64_t digit = (uint64_t)field[index] - (uint64_t)(uint8_t)
'0';
115 value = (value << 3U) + digit;
130 unsigned checksum = 0U;
135 uint64_t expected = 0U;
140 ((uint64_t)checksum != expected) ||
179 zero = zero && (state->
block[i] == 0U);
205 while (offset < length) {
207 if (bytes[offset++] != 0U) {
213 const uint64_t available = (uint64_t)length - (uint64_t)offset;
214 const size_t consumed =
221 const size_t copied = ((length - offset) < missing) ? (length - offset) : missing;
249 report->page_count = state->
pages;
250 report->member_count = state->
members;
251 report->metadata_present = state->
metadata;
266 }
else if (got == 0U) {
299 gzip->
stream.next_in = bytes;
300 gzip->
stream.avail_in = length;
302 const mz_uint before_in = gzip->
stream.avail_in;
305 const int status = mz_inflate(&gzip->
stream, MZ_NO_FLUSH);
307 if (gzip->
raw_bytes > (uint64_t)UINT32_MAX - produced) {
310 if (produced != 0U) {
315 gzip->
crc = (uint32_t)mz_crc32(gzip->
crc, gzip->
output, produced);
318 if (status == MZ_STREAM_END) {
322 if ((status != MZ_OK) || ((before_in == gzip->
stream.avail_in) && (produced == 0U))) {
325 }
while ((gzip->
stream.avail_in != 0U) || (gzip->
stream.avail_out == 0U));
337 const uint8_t empty_input = 0U;
338 while (!gzip->
ended) {
344 if (!gzip->
ended && (gzip->
stream.avail_out != 0U)) {
400 gzip->
stream.opaque = arena;
401 if ((gzip->
output ==
nullptr) ||
402 (mz_inflateInit2(&gzip->
stream, -MZ_DEFAULT_WINDOW_BITS) != MZ_OK)) {
431 uint64_t left = remaining;
432 while ((error ==
k_ra8_ok) && (left != 0U) && !gzip->
ended) {
433 const uint32_t chunk =
477 const uint64_t remaining =
481 if (gzip.
stream.state !=
nullptr) {
482 (void)mz_inflateEnd(&gzip.
stream);
struct mdl_export_workspace mdl_export_workspace_t
Caller-owned bounded arena for all exporter scratch state.
@ k_gzip_header_bytes
Fixed RFC 1952 header.
@ k_mdl_storage_io_bytes
One bounded read/write chunk.
void priv_mdl_verify_arena_free(void *opaque, void *address)
Accept a miniz free for a monotonic arena.
ra8_err_t priv_mdl_verify_io_read_up_to(mdl_verify_io_t *io, uint8_t *destination, size_t length, size_t *out_read)
Read up to a requested portable span.
bool priv_mdl_verify_safe_member_name(const char *name)
Reject unsafe archive member paths.
void * priv_mdl_verify_workspace_take(mdl_export_workspace_t *workspace, size_t bytes, size_t alignment)
Reserve one aligned span from the verifier's caller-owned arena.
void * priv_mdl_verify_arena_alloc(void *opaque, size_t items, size_t size)
Allocate one aligned miniz span from a monotonic arena.
bool priv_mdl_verify_is_image(const char *name)
Recognize supported image suffixes.
Private bounded validator seams shared by the mdl verifiers.
@ k_verify_member_max
Maximum archive member count.
static ra8_err_t internal_io_read_exact(mdl_verify_io_t *io, uint8_t *destination, size_t length)
Read one exact structural span.
mdl_verify_gzip_frame_t
Fixed RFC 1952 framing emitted and accepted by mdl.
@ k_gzip_min_bytes
Smallest fixed-frame gzip extent.
@ k_gzip_method_deflate
RFC 1952 DEFLATE method identifier.
@ k_gzip_id_two
Second RFC 1952 magic byte.
@ k_gzip_id_one
First RFC 1952 magic byte.
@ k_gzip_trailer_bytes
CRC32 plus ISIZE trailer extent.
@ k_gzip_isize_offset
ISIZE offset inside that trailer.
ra8_err_t priv_mdl_verify_tar(mdl_verify_io_t *io, mdl_verify_report_t *report)
Validate an uncompressed CBT.
static ra8_err_t internal_gzip_consume(mdl_verify_io_t *io, mdl_verify_arena_t *arena, mdl_gzip_stream_t *gzip, uint64_t remaining)
Feed the compressed remainder into the inflater and validate the trailer.
static ra8_err_t internal_tar_process_block(mdl_tar_stream_t *state)
Process one complete 512-byte TAR block once fully buffered.
static ra8_err_t internal_gzip_feed(mdl_gzip_stream_t *gzip, const uint8_t *bytes, uint32_t length)
Inflate a raw-DEFLATE chunk.
mdl_verify_tar_layout_t
POSIX tar field layout and record sizing.
@ k_tar_checksum_offset
USTAR checksum-field byte offset.
@ k_tar_checksum_end
First byte after the checksum field.
@ k_tar_padding_mask
Mask used to round payloads to records.
@ k_tar_size_offset
USTAR size-field byte offset.
@ k_tar_type_offset
USTAR type-flag byte offset.
@ k_tar_block_bytes
TAR logical record extent.
@ k_tar_size_bytes
USTAR size-field extent.
@ k_tar_name_bytes
USTAR name-field extent.
static ra8_err_t internal_gzip_finish_deflate(mdl_gzip_stream_t *gzip)
Finish raw-DEFLATE validation.
mdl_verify_u32_shift_t
Byte shifts for little-endian decoding.
@ k_u32_byte_three_shift
Shift for byte three.
@ k_u32_byte_two_shift
Shift for byte two.
@ k_u32_byte_one_shift
Shift for byte one.
static ra8_err_t internal_tar_member(mdl_tar_stream_t *state)
Validate one TAR header.
static bool internal_gzip_header_valid(const uint8_t *header)
Validate the fixed gzip header.
ra8_err_t priv_mdl_verify_gzip_tar(mdl_verify_io_t *io, mdl_export_workspace_t *workspace, mdl_verify_report_t *report)
Validate a gzip-compressed CBT.
static ra8_err_t internal_tar_feed(mdl_tar_stream_t *state, const uint8_t *bytes, size_t length)
Feed bytes into TAR validation.
static uint32_t internal_get_u32le(const uint8_t *bytes)
Decode one little-endian word.
static ra8_err_t internal_gzip_init_inflate(mdl_export_workspace_t *workspace, mdl_verify_arena_t *arena, mdl_gzip_stream_t *gzip)
Initialize the gzip inflater bound to workspace-backed scratch.
static bool internal_gzip_trailer_valid(const uint8_t *trailer, const mdl_gzip_stream_t *gzip)
Validate gzip trailer accounting.
static ra8_err_t internal_tar_finish(const mdl_tar_stream_t *state, mdl_verify_report_t *report)
Finish TAR validation.
static bool internal_parse_octal(const uint8_t *field, size_t length, uint64_t *out)
Parse a bounded TAR octal field.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
int strcmp(const char *s1, const char *s2)
Compare two null-terminated strings.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Streaming gzip inflater and nested TAR consumer.
uint32_t crc
Running decoded CRC32.
mz_stream stream
Raw-DEFLATE miniz state.
uint32_t output_cap
Extent of output.
bool ended
DEFLATE end marker observed.
mdl_tar_stream_t tar
Incremental decoded TAR state.
uint8_t * output
One bounded decoded chunk.
uint64_t raw_bytes
Exact decoded byte count.
One non-reentrant downloader filesystem dependency bundle.
uint8_t * io_buffer
Caller-owned stream scratch.
uint32_t io_buffer_bytes
Stream scratch extent.
Incremental TAR structural state.
bool metadata
ComicInfo.xml was found.
uint8_t zero_blocks
Consecutive terminal records.
bool ended
Two zero blocks were consumed.
size_t members
Regular member count.
uint8_t block[k_tar_block_bytes]
Partial header record.
uint64_t skip_bytes
Padded payload remaining.
uint64_t total_bytes
Total decoded TAR bytes.
size_t pages
Image member count.
size_t block_used
Bytes resident in block.
Allocation bridge retaining an explicit capacity failure.
bool exhausted
An allocation did not fit.
One open portable input and its immutable size snapshot.