Skip to content
BufIterFromMemory

BufIterFromMemory

Description

Construct a BufIter over [data, data + length). The iterator borrows the caller’s bytes – ownership is unchanged.

Success

Returns a BufIter positioned at offset 0 with stride 1 and forward direction.

Failure

Macro cannot fail. Passing a NULL data_ with non-zero length_ is a usage error – subsequent reads will dereference NULL.

Usage example (Cross-references)

Usage examples (Cross-references)
    /// TAGS: Buf, Iter, Construct
    ///
    #define BufIterFromBuf(b_) BufIterFromMemory(BufData(b_), BufLength(b_))
    
    // ---------------------------------------------------------------------------
            return false;
        }
        BufIter mz_iter = BufIterFromMemory(BufData(&ctx->out->data), 2);
        u16     mz;
        if (!BufReadU16LE(&mz_iter, &mz)) {
        }
        u32     e_lfanew;
        BufIter c = BufIterFromMemory(
            BufData(&ctx->out->data) + DOS_E_LFANEW_OFFSET,
            BufLength(&ctx->out->data) - DOS_E_LFANEW_OFFSET
    static bool pe_decode_nt(PeContext *ctx, u64 *out_opt_offset) {
        BufIter c =
            BufIterFromMemory(BufData(&ctx->out->data) + ctx->nt_offset, BufLength(&ctx->out->data) - ctx->nt_offset);
        u32 sig;
        if (!BufReadU32LE(&c, &sig) || sig != NT_SIGNATURE) {
            return false;
        }
        BufIter c = BufIterFromMemory(BufData(&ctx->out->data) + opt_offset, ctx->opt_hdr_size);
    
        u16 magic;
    static bool pe_decode_sections(PeContext *ctx, u64 opt_offset) {
        u64     sec_offset = opt_offset + ctx->opt_hdr_size;
        BufIter c = BufIterFromMemory(BufData(&ctx->out->data) + sec_offset, BufLength(&ctx->out->data) - sec_offset);
    
        for (u32 i = 0; i < ctx->num_sections; ++i) {
        for (u32 i = 0; i < num_entries; ++i) {
            u64     entry_off = dir_offset + (u64)i * DEBUG_ENTRY_SIZE;
            BufIter c = BufIterFromMemory(BufData(&ctx->out->data) + entry_off, BufLength(&ctx->out->data) - entry_off);
            u32     charac, ts, type, sz, raddr, rptr;
            u16     ver_maj, ver_min;
            if (sz < 4 + 16 + 4 + 1)
                continue;
            BufIter cv_cur = BufIterFromMemory(BufData(&ctx->out->data) + rptr, sz);
            u32     cv_sig;
            if (!BufReadU32LE(&cv_cur, &cv_sig))
        }
    
        BufIter info_cur = BufIterFromMemory(info_bytes, info_size);
    
        PendingFns pending = VecInitT(pending, alloc);
    
            AbbrevTable abbrevs;
            BufIter     abbrev_cur = BufIterFromMemory(abbrev_bytes + abbrev_offset, abbrev_size - abbrev_offset);
            if (!parse_abbrev_table(abbrev_cur, &abbrevs, alloc)) {
                ok = false;
            // info_cur position up to unit_end_pos).
            BufIter die_cur =
                BufIterFromMemory(IterDataAt(&info_cur, IterIndex(&info_cur)), unit_end_pos - IterIndex(&info_cur));
            if (!walk_cu_dies(die_cur, &abbrevs, addr_size, str_bytes, str_size, &out->string_pool, &pending)) {
                abbrev_table_deinit(&abbrevs);
            return false;
        }
        BufIter it = BufIterFromMemory(buf, len);
        u16     flags, qd, an, ns, ar;
        if (!BufReadFmt(&it, "{>2r}{>2r}{>2r}{>2r}{>2r}{>2r}", out->id, flags, qd, an, ns, ar)) {
            return false;
        }
        BufIter sb = BufIterFromMemory(BufData(&self->data) + 32, BufLength(&self->data) - 32);
        u32     free_blk, num_blocks, unknown;
        if (!BufReadFmt(
    
        for (u32 i = 0; i < num_dir_blocks; ++i) {
            BufIter blk_iter = BufIterFromMemory((const u8 *)&self->dir_stream_blocks[i], sizeof(u32));
            u32     block_id;
            if (!BufReadU32LE(&blk_iter, &block_id)) {
            return false;
        }
        BufIter dir_iter = BufIterFromMemory(self->stream_dir, self->stream_dir_size);
        if (!BufReadU32LE(&dir_iter, &self->num_streams))
            return false;
            if (!stream_read(self, 1, 0, VecBegin(&buf), VecCapacity(&buf)))
                break;
            BufIter bi = BufIterFromMemory(VecBegin(&buf), VecCapacity(&buf));
            if (!BufReadFmt(&bi, FMT_PDB_INFO_LE, self->info.version, self->info.signature, self->info.age)) {
                LOG_ERROR("PDB: info stream prefix truncated");
                break;
    
            BufIter bi = BufIterFromMemory(VecBegin(&hdr), VecCapacity(&hdr));
            if (!BufReadFmt(
                    &bi,
        for (u32 i = 0; i < n; ++i) {
            // IMAGE_SECTION_HEADER: name[8] + VirtualSize(4) + VirtualAddress(4) + ...
            BufIter rec = BufIterFromMemory(buf + i * 40 + 8, 40 - 8);
            (void)BufReadU32LE(&rec, &out[i].virtual_size);
            (void)BufReadU32LE(&rec, &out[i].virtual_address);
        u64 cur = 0;
        while (cur + 4 <= (u64)sz) {
            BufIter rec_iter = BufIterFromMemory(buf + cur, 4);
            u16     rec_len, rec_kind;
            if (!BufReadU16LE(&rec_iter, &rec_len) || !BufReadU16LE(&rec_iter, &rec_kind))
                // Record body starts at cur + 4 (past len + kind). 10-byte
                // prefix (Flags/Offset/Segment) then NUL-terminated Name.
                BufIter body = BufIterFromMemory(buf + cur + 4, rec_len - 2);
                u32     flags, offset;
                u16     segment;
            return false;
    
        BufIter    it = BufIterFromMemory((u8 *)data, len);
        TzifHeader h1;
        if (!tzif_read_header(&it, &h1)) {
        cfi_parse_section(DwarfCfi *out, const u8 *section_data, u64 section_addr, u64 section_size, bool is_debug_frame) {
        const u32 cie_id      = is_debug_frame ? 0xffffffffu : 0u;
        BufIter   section_cur = BufIterFromMemory(section_data, section_size);
        while (IterRemainingLength(&section_cur) > 0) {
            const u8 *rec_start = IterDataAt(&section_cur, IterIndex(&section_cur));
                // Body iter starts just after the id field (since parse_cie
                // doesn't re-read id) and spans the remainder of the record.
                BufIter body = BufIterFromMemory(IterDataAt(&section_cur, IterIndex(&section_cur)), length32 - 4);
                if (parse_cie(&body, cie_offset, &cie)) {
                    if (!VecPushBackR(&out->cies, cie))
                }
                DwarfFde fde;
                BufIter  body = BufIterFromMemory(IterDataAt(&section_cur, IterIndex(&section_cur)), length32 - 4);
                if (parse_fde(&body, rec_start, cie_offset, out, section_data, section_addr, &fde)) {
                    if (!VecPushBackR(&out->fdes, fde))
    
    static bool cfi_vm_run(CfiVm *vm, const u8 *insns, u64 insns_size, u64 stop_at) {
        BufIter cur      = BufIterFromMemory(insns, insns_size);
        bool    stop_now = false;
        while (IterRemainingLength(&cur) > 0) {
        }
    
        BufIter it = BufIterFromMemory(BufData(&self->data) + note->offset, note->size);
    
        u32 namesz = 0, descsz = 0, type = 0;
        // CRC is in the last 4 bytes.
        const u8 *crc_bytes = BufData(&self->data) + dl->offset + dl->size - 4;
        BufIter   crc_iter  = BufIterFromMemory(crc_bytes, 4);
        u32       crc;
        if (!BufReadU32LE(&crc_iter, &crc)) {
        U64Vec pending_dir_offsets  = VecInitT(pending_dir_offsets, alloc);
    
        BufIter section_cur = BufIterFromMemory(BufData(ElfBuf(elf)) + line_section->offset, line_section->size);
    
        bool ok = true;
            // up to the end of this CU.
            size    strings_start_pos = (size)(hdr.strings_start - IterDataAt(&section_cur, 0));
            BufIter str_cur           = BufIterFromMemory(IterDataAt(&section_cur, 0), unit_end_pos);
            // strings_start_pos lies within `[0, unit_end_pos]` by construction
            // -- `hdr.strings_start` was assigned from inside this section's
    
            // Skip past the tables to find the program body start.
            BufIter prog_anchor = BufIterFromMemory(IterDataAt(&section_cur, 0), unit_end_pos);
            // Must-precondition: same bounds proof as `str_cur` above --
            // `strings_start_pos` is inside `[0, unit_end_pos]` by header
    bool test_byte_iter_from_memory(void) {
        const u8 bytes[] = {0xAA, 0xBB, 0xCC};
        BufIter  it      = BufIterFromMemory(bytes, 3);
        u8       v;
        bool     ok = BufReadU8(&it, &v) && v == 0xAA;
    bool deadend_must_read_eof(void) {
        const u8 buf[1] = {1};
        BufIter  it     = BufIterFromMemory(buf, 1);
        u8       v;
        IterRead(&it, &v);
    bool deadend_must_peek_out_of_range(void) {
        const u8 buf[1] = {1};
        BufIter  it     = BufIterFromMemory(buf, 1);
        u8       v;
        IterMustPeekAt(&it, 1, &v);
    bool deadend_must_move_overflow(void) {
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        IterMustMove(&it, 4);
        return true;
    bool deadend_must_next_eof(void) {
        const u8 buf[1] = {0};
        BufIter  it     = BufIterFromMemory(buf, 1);
        u8       v;
        IterRead(&it, &v);
    bool deadend_must_prev_underflow(void) {
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        IterMustPrev(&it);
        return true;
    bool test_iter_remaining_forward(void) {
        const u8 buf[3] = {1, 2, 3};
        BufIter  it     = BufIterFromMemory(buf, 3);
        if (IterRemainingLength(&it) != 3) {
            return false;
    bool test_iter_read_forward(void) {
        const u8 buf[3] = {10, 20, 30};
        BufIter  it     = BufIterFromMemory(buf, 3);
        u8       v      = 0;
        if (!IterRead(&it, &v) || v != 10) {
    bool test_iter_read_eof_leaves_state(void) {
        const u8 buf[1] = {7};
        BufIter  it     = BufIterFromMemory(buf, 1);
        u8       v      = 0;
        IterRead(&it, &v);
    bool test_iter_peek_in_range(void) {
        const u8 buf[4] = {5, 6, 7, 8};
        BufIter  it     = BufIterFromMemory(buf, 4);
        IterMove(&it, 2);
        u8 v;
    bool test_iter_peek_out_of_range(void) {
        const u8 buf[2] = {1, 2};
        BufIter  it     = BufIterFromMemory(buf, 2);
        u8       v      = 0xAA;
        if (IterPeekAt(&it, 2, &v)) {
    bool test_iter_move_forward_basic(void) {
        const u8 buf[5] = {0};
        BufIter  it     = BufIterFromMemory(buf, 5);
        if (!IterMove(&it, 3) || IterIndex(&it) != 3) {
            return false;
    bool test_iter_move_forward_to_exhausted(void) {
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        if (!IterMove(&it, 3) || IterIndex(&it) != 3) {
            return false;
    bool test_iter_move_forward_overflow(void) {
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        size     before = IterIndex(&it);
        if (IterMove(&it, 4)) {
    bool test_iter_move_forward_underflow(void) {
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        if (IterMove(&it, -1)) {
            return false;
    bool test_iter_next_prev(void) {
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        if (!IterNext(&it) || IterIndex(&it) != 1) {
            return false;
    bool test_it_validate_accepts_forward(void) {
        const u8 buf[2] = {1, 2};
        BufIter  it     = BufIterFromMemory(buf, 2);
        ValidateIter(&it);
        return true;
    bool test_iter_pos_current_and_exhausted(void) {
        const u8 buf[2] = {40, 50};
        BufIter  it     = BufIterFromMemory(buf, 2);
        if (IterPos(&it) != &buf[0] || *IterPos(&it) != 40) {
            return false;
    bool test_iter_data_at_index_and_end(void) {
        const u8 buf[3] = {7, 8, 9};
        BufIter  it     = BufIterFromMemory(buf, 3);
        IterMove(&it, 1); // cursor moves; DataAt must ignore it
        if (IterDataAt(&it, 0) != &buf[0] || *IterDataAt(&it, 2) != 9) {
    bool test_iter_truncate_caps_reads(void) {
        const u8 buf[5] = {1, 2, 3, 4, 5};
        BufIter  it     = BufIterFromMemory(buf, 5);
        IterMove(&it, 1);     // cursor at index 1
        IterTruncate(&it, 2); // only indices 1,2 remain reachable
    bool test_iter_carve_child_range(void) {
        const u8 buf[4] = {10, 20, 30, 40};
        BufIter  parent = BufIterFromMemory(buf, 4);
        IterMove(&parent, 1); // parent cursor at index 1
        BufIter child = IterCarve(&parent, 2);
Last updated on