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)
- In
Buf.h:147:
/// TAGS: Buf, Iter, Construct
///
#define BufIterFromBuf(b_) BufIterFromMemory(BufData(b_), BufLength(b_))
// ---------------------------------------------------------------------------
- In
Pe.c:163:
return false;
}
BufIter mz_iter = BufIterFromMemory(BufData(&ctx->out->data), 2);
u16 mz;
if (!BufReadU16LE(&mz_iter, &mz)) {- In
Pe.c:173:
}
u32 e_lfanew;
BufIter c = BufIterFromMemory(
BufData(&ctx->out->data) + DOS_E_LFANEW_OFFSET,
BufLength(&ctx->out->data) - DOS_E_LFANEW_OFFSET- In
Pe.c:190:
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) {- In
Pe.c:220:
return false;
}
BufIter c = BufIterFromMemory(BufData(&ctx->out->data) + opt_offset, ctx->opt_hdr_size);
u16 magic;- In
Pe.c:376:
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) {- In
Pe.c:446:
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;- In
Pe.c:465:
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))- In
DwarfInfo.c:536:
}
BufIter info_cur = BufIterFromMemory(info_bytes, info_size);
PendingFns pending = VecInitT(pending, alloc);- In
DwarfInfo.c:585:
AbbrevTable abbrevs;
BufIter abbrev_cur = BufIterFromMemory(abbrev_bytes + abbrev_offset, abbrev_size - abbrev_offset);
if (!parse_abbrev_table(abbrev_cur, &abbrevs, alloc)) {
ok = false;- In
DwarfInfo.c:594:
// 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);- In
Dns.c:283:
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)) {- In
Pdb.c:151:
return false;
}
BufIter sb = BufIterFromMemory(BufData(&self->data) + 32, BufLength(&self->data) - 32);
u32 free_blk, num_blocks, unknown;
if (!BufReadFmt(- In
Pdb.c:205:
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)) {- In
Pdb.c:237:
return false;
}
BufIter dir_iter = BufIterFromMemory(self->stream_dir, self->stream_dir_size);
if (!BufReadU32LE(&dir_iter, &self->num_streams))
return false;- In
Pdb.c:331:
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");- In
Pdb.c:375:
break;
BufIter bi = BufIterFromMemory(VecBegin(&hdr), VecCapacity(&hdr));
if (!BufReadFmt(
&bi,- In
Pdb.c:490:
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);- In
Pdb.c:563:
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))- In
Pdb.c:576:
// 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;- In
Tzif.c:158:
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(§ion_cur) > 0) {
const u8 *rec_start = IterDataAt(§ion_cur, IterIndex(§ion_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(§ion_cur, IterIndex(§ion_cur)), length32 - 4);
if (parse_cie(&body, cie_offset, &cie)) {
if (!VecPushBackR(&out->cies, cie)) }
DwarfFde fde;
BufIter body = BufIterFromMemory(IterDataAt(§ion_cur, IterIndex(§ion_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) {- In
Elf.c:410:
}
BufIter it = BufIterFromMemory(BufData(&self->data) + note->offset, note->size);
u32 namesz = 0, descsz = 0, type = 0;- In
Elf.c:448:
// 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)) {- In
Dwarf.c:560:
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;- In
Dwarf.c:603:
// up to the end of this CU.
size strings_start_pos = (size)(hdr.strings_start - IterDataAt(§ion_cur, 0));
BufIter str_cur = BufIterFromMemory(IterDataAt(§ion_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
- In
Dwarf.c:615:
// Skip past the tables to find the program body start.
BufIter prog_anchor = BufIterFromMemory(IterDataAt(§ion_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
- In
Buf.c:253:
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;- In
Deadend.c:15:
bool deadend_must_read_eof(void) {
const u8 buf[1] = {1};
BufIter it = BufIterFromMemory(buf, 1);
u8 v;
IterRead(&it, &v);- In
Deadend.c:24:
bool deadend_must_peek_out_of_range(void) {
const u8 buf[1] = {1};
BufIter it = BufIterFromMemory(buf, 1);
u8 v;
IterMustPeekAt(&it, 1, &v);- In
Deadend.c:32:
bool deadend_must_move_overflow(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
IterMustMove(&it, 4);
return true;- In
Deadend.c:39:
bool deadend_must_next_eof(void) {
const u8 buf[1] = {0};
BufIter it = BufIterFromMemory(buf, 1);
u8 v;
IterRead(&it, &v);- In
Deadend.c:48:
bool deadend_must_prev_underflow(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
IterMustPrev(&it);
return true;- In
Iter.c:21:
bool test_iter_remaining_forward(void) {
const u8 buf[3] = {1, 2, 3};
BufIter it = BufIterFromMemory(buf, 3);
if (IterRemainingLength(&it) != 3) {
return false;- In
Iter.c:53:
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) {- In
Iter.c:87:
bool test_iter_read_eof_leaves_state(void) {
const u8 buf[1] = {7};
BufIter it = BufIterFromMemory(buf, 1);
u8 v = 0;
IterRead(&it, &v);- In
Iter.c:102:
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;- In
Iter.c:120:
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)) {- In
Iter.c:137:
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;- In
Iter.c:149:
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;- In
Iter.c:158:
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)) {- In
Iter.c:168:
bool test_iter_move_forward_underflow(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
if (IterMove(&it, -1)) {
return false;- In
Iter.c:212:
bool test_iter_next_prev(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
if (!IterNext(&it) || IterIndex(&it) != 1) {
return false;- In
Iter.c:337:
bool test_it_validate_accepts_forward(void) {
const u8 buf[2] = {1, 2};
BufIter it = BufIterFromMemory(buf, 2);
ValidateIter(&it);
return true;- In
Iter.c:376:
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;- In
Iter.c:389:
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) {- In
Iter.c:415:
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
- In
Iter.c:437:
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