IterIndex
Description
Absolute cursor index within the iterator’s backing region. Read-only accessor for (mi)->pos; use it from outside the Iter namespace instead of reaching for the field. Forward iterators report a value in [0, length] (where length is the past-end position); reverse iterators report [0, length-1] plus the (size)-1 past-start sentinel.
Usage example (Cross-references)
Usage examples (Cross-references)
- In
MachO.c:185:
// plus the 16-byte segname plus the body.
IterMustMove(cmd, 8); // skip cmd(4) + cmdsize(4) prefix
MemCopy(seg.name, IterDataAt(cmd, IterIndex(cmd)), 16);
seg.name[16] = '\0';
IterMustMove(cmd, 16);- In
MachO.c:213:
// SECT64_SIZE bytes.
for (u32 i = 0; i < seg.nsects; ++i) {
if (IterIndex(cmd) + SECT64_SIZE > IterLength(cmd)) {
LOG_ERROR("MachO: section table overruns LC_SEGMENT_64");
return false;- In
MachO.c:222:
MachoSection sec;
MemSet(&sec, 0, sizeof(sec));
MemCopy(sec.section, IterDataAt(&sec_it, IterIndex(&sec_it)), 16);
sec.section[16] = '\0';
IterMustMove(&sec_it, 16);- In
MachO.c:225:
sec.section[16] = '\0';
IterMustMove(&sec_it, 16);
MemCopy(sec.segment, IterDataAt(&sec_it, IterIndex(&sec_it)), 16);
sec.segment[16] = '\0';
IterMustMove(&sec_it, 16);- In
MachO.c:286:
// proves the 8-byte prefix plus the 16-byte UUID payload fit.
IterMustMove(cmd, 8); // skip cmd + cmdsize prefix
MemCopy(ctx->out->uuid, IterDataAt(cmd, IterIndex(cmd)), 16);
ctx->out->has_uuid = true;
return true;- In
Dwarf.c:160:
if (IterRemainingLength(cur) < out->std_opcode_lengths_count)
return false;
out->standard_opcode_lengths = IterDataAt(cur, IterIndex(cur));
// Must-precondition: the `IterRemainingLength < count` guard above
// proves the cursor has at least `count` bytes left in the buffer.
- In
Dwarf.c:164:
// proves the cursor has at least `count` bytes left in the buffer.
IterMustMove(cur, (i64)out->std_opcode_lengths_count);
out->strings_start = IterDataAt(cur, IterIndex(cur));
return true;
}- In
Dwarf.c:171:
// start of the line number program body.
static bool skip_line_program_tables(BufIter *cur) {
while (IterIndex(cur) < IterLength(cur) && *IterDataAt(cur, IterIndex(cur)) != 0) {
if (!BufReadZstr(cur))
return false;- In
Dwarf.c:177:
// Must-precondition: the surrounding `IterIndex < IterLength` test
// proves there is at least one more byte to consume (the NUL).
if (IterIndex(cur) < IterLength(cur))
IterMustNext(cur); // empty terminator
- In
Dwarf.c:180:
IterMustNext(cur); // empty terminator
while (IterIndex(cur) < IterLength(cur) && *IterDataAt(cur, IterIndex(cur)) != 0) {
if (!BufReadZstr(cur))
return false;- In
Dwarf.c:193:
// Must-precondition: same `IterIndex < IterLength` proof as the
// include_directories terminator above.
if (IterIndex(cur) < IterLength(cur))
IterMustNext(cur); // empty terminator
return true;- In
Dwarf.c:229:
static bool collect_cu_strings(BufIter cur, Str *pool, CuStrings *cs) {
// include_directories
while (IterIndex(&cur) < IterLength(&cur) && *IterDataAt(&cur, IterIndex(&cur)) != 0) {
Zstr dir = BufReadZstr(&cur);
if (!dir)- In
Dwarf.c:241:
// Must-precondition: `IterIndex < IterLength` proves there is a
// terminator byte left to consume.
if (IterIndex(&cur) < IterLength(&cur))
IterMustNext(&cur); // empty terminator
- In
Dwarf.c:245:
// file_names
while (IterIndex(&cur) < IterLength(&cur) && *IterDataAt(&cur, IterIndex(&cur)) != 0) {
Zstr name = BufReadZstr(&cur);
if (!name)- In
Dwarf.c:344:
lnp_reset(&st, hdr->default_is_stmt);
while (IterDataAt(&cur, IterIndex(&cur)) < prog_end) {
u8 op = 0;
if (!BufReadU8(&cur, &op))- In
Dwarf.c:354:
if (!BufReadULeb128(&cur, &length))
return false;
if (length == 0 || (u64)(prog_end - IterDataAt(&cur, IterIndex(&cur))) < length)
return false;
const u8 *body_end = IterDataAt(&cur, IterIndex(&cur)) + length;- In
Dwarf.c:356:
if (length == 0 || (u64)(prog_end - IterDataAt(&cur, IterIndex(&cur))) < length)
return false;
const u8 *body_end = IterDataAt(&cur, IterIndex(&cur)) + length;
u8 sub_op = 0;
if (!BufReadU8(&cur, &sub_op))- In
Dwarf.c:369:
case DW_LNE_SET_ADDRESS :
// operand size = remaining body bytes; on x86-64 always 8.
if (body_end - IterDataAt(&cur, IterIndex(&cur)) == 8) {
if (!BufReadU64LE(&cur, &st.address))
return false;- In
Dwarf.c:372:
if (!BufReadU64LE(&cur, &st.address))
return false;
} else if (body_end - IterDataAt(&cur, IterIndex(&cur)) == 4) {
u32 a32 = 0;
if (!BufReadU32LE(&cur, &a32))- In
Dwarf.c:398:
// above proved `length <= prog_end - here`, and switch arms
// only consume bytes within the body. Jump to body_end.
IterMustMove(&cur, (i64)((size)(body_end - IterDataAt(&cur, 0)) - IterIndex(&cur)));
} else if (op < hdr->opcode_base) {
// Standard opcode
- In
Dwarf.c:564:
bool ok = true;
while (IterRemainingLength(§ion_cur) > 0) {
const u8 *unit_start = IterDataAt(§ion_cur, IterIndex(§ion_cur));
u32 unit_length = 0;
BufIter peek = section_cur;- In
Dwarf.c:581:
}
const u8 *unit_end = unit_start + 4 + unit_length;
size unit_end_pos = IterIndex(§ion_cur) + 4 + unit_length;
// Decode header (fields only), then walk the directory / file
- In
Dwarf.c:593:
// consumed gives us the size of this whole unit.
// unit_end_pos was bounded above against the section end.
IterMustMove(§ion_cur, (i64)(unit_end_pos - IterIndex(§ion_cur)));
continue;
}- In
Dwarf.c:635:
cu_strings_deinit(&cs);
// Same bounds proof as the unsupported-version branch above.
IterMustMove(§ion_cur, (i64)(unit_end_pos - IterIndex(§ion_cur)));
}- In
DwarfInfo.c:542:
bool ok = true;
while (IterRemainingLength(&info_cur) > 0) {
size unit_start_pos = IterIndex(&info_cur);
u32 unit_length;- In
DwarfInfo.c:574:
// up the rest of the binary's CUs in case some are v4.
// unit_end_pos was bounded above against IterLength(&info_cur).
IterMustMove(&info_cur, (i64)(unit_end_pos - IterIndex(&info_cur)));
continue;
}- 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
DwarfInfo.c:603:
// Same bounds proof: unit_end_pos was bounded above.
IterMustMove(&info_cur, (i64)(unit_end_pos - IterIndex(&info_cur)));
}- In
Pdb.c:583:
continue;
}
Zstr name = (Zstr)IterDataAt(&body, IterIndex(&body));
(void)flags; // permissive: we don't filter by FUNCTION bit;
if (aug_len > IterRemainingLength(body))
return false;
size aug_end_pos = IterIndex(body) + aug_len;
StrIter aug_it = StrIterFromZstr(augmentation + 1); // before we started reading; even a partial-arm read leaves the
// cursor inside `[aug_start, aug_end_pos]`.
IterMustMove(body, (i64)(aug_end_pos - IterIndex(body)));
} }
out->initial_instructions = IterDataAt(body, IterIndex(body));
out->initial_instructions_size = IterRemainingLength(body);
return true; u64 pc_begin = 0;
{
u64 here = eh_byte_vaddr(section_data, section_addr, IterDataAt(body, IterIndex(body)));
if (!decode_eh_ptr(body, cie->fde_pointer_encoding, here, &pc_begin))
return false; u64 pc_range = 0;
{
u64 here = eh_byte_vaddr(section_data, section_addr, IterDataAt(body, IterIndex(body)));
if (!decode_eh_ptr(body, range_enc, here, &pc_range))
return false; }
out->instructions = IterDataAt(body, IterIndex(body));
out->instructions_size = IterRemainingLength(body);
return true; BufIter section_cur = BufIterFromMemory(section_data, eh->size);
while (IterRemainingLength(§ion_cur) > 0) {
const u8 *rec_start = IterDataAt(§ion_cur, IterIndex(§ion_cur));
u32 length32 = 0;
if (!BufReadU32LE(§ion_cur, &length32)) // We've already consumed 4 bytes for `id`, so the body iter
// covers (id field's start) + length32 bytes.
size body_pos_start = IterIndex(§ion_cur) - 4;
// In .eh_frame, id==0 means CIE; nonzero is the CIE_pointer for FDE
// 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)) { // miss every CIE (best case) or alias one (worst case).
// Skip the FDE explicitly.
u64 id_field_off = (u64)(IterIndex(§ion_cur) - 4);
if ((u64)id > id_field_off) {
// length32 bounds were validated against IterRemainingLength
u64 cie_offset = id_field_off - (u64)id;
DwarfFde fde;
BufIter body = BufIterFromMemory(IterDataAt(§ion_cur, IterIndex(§ion_cur)), length32 - 4);
if (parse_fde(&body, rec_start, cie_offset, out, section_data, eh->addr, &fde)) {
if (!VecPushBackR(&out->fdes, fde)) {
// Same bounds proof as above: jump past this record's body.
IterMustMove(§ion_cur, (i64)((body_pos_start + length32) - IterIndex(§ion_cur)));
}- In
Dns.c:106:
u32 hops = 0;
bool jumped = false;
u64 linear_p = IterIndex(it);
u64 cur = IterIndex(it);
u64 name_len = 0;- In
Dns.c:107:
bool jumped = false;
u64 linear_p = IterIndex(it);
u64 cur = IterIndex(it);
u64 name_len = 0;
u64 label_idx = 0;- In
Dns.c:121:
// compression-pointer branch sets `linear_p = cur + 2` BEFORE
// jumping). Net delta is always >= 0 and within `IterLength(it)`.
IterMustMove(it, (i64)(linear_p - IterIndex(it)));
return true;
}- In
Dns.c:195:
rec->ttl = ttl;
if (IterIndex(it) + (u64)rdlength > IterLength(it)) {
return false;
}- In
Dns.c:198:
return false;
}
u64 rdata_start = IterIndex(it);
// Stash raw rdata.
- In
Pe.c:209:
ctx->num_sections = num_sec;
ctx->opt_hdr_size = size_opt;
*out_opt_offset = (u64)(IterDataAt(&c, IterIndex(&c)) - BufData(&ctx->out->data));
return true;
}- In
Pe.c:386:
// 8-byte name: bytes, not a numeric, so copy + advance manually.
// IterRemainingLength >= 40 bound above proves 8 bytes are live.
MemCopy(s.name, IterDataAt(&c, IterIndex(&c)), 8);
s.name[8] = '\0';
IterMustMove(&c, 8);- In
Pe.c:477:
continue;
// Same proof: 16 bytes are live.
MemCopy(cv->guid, IterDataAt(&cv_cur, IterIndex(&cv_cur)), 16);
IterMustMove(&cv_cur, 16);
if (!BufReadU32LE(&cv_cur, &cv->age))- In
Pe.c:482:
continue;
// Verify the trailing path is NUL-terminated inside the record.
const u8 *path_start = IterDataAt(&cv_cur, IterIndex(&cv_cur));
const u8 *region_end = IterDataAt(&cv_cur, IterLength(&cv_cur));
bool terminated = false;- In
Iter.c:86:
u8 v = 0;
IterRead(&it, &v);
size pos_before = IterIndex(&it);
u8 sentinel = 0xAA;
v = sentinel;- In
Iter.c:93:
}
// Failed read must leave both `pos` and `*out` untouched.
return IterIndex(&it) == pos_before && v == sentinel;
}- In
Iter.c:111:
}
// Peeks must not advance the cursor.
return IterIndex(&it) == 2;
}- In
Iter.c:134:
const u8 buf[5] = {0};
BufIter it = BufIterFromMemory(buf, 5);
if (!IterMove(&it, 3) || IterIndex(&it) != 3) {
return false;
}- In
Iter.c:137:
return false;
}
if (!IterMove(&it, -2) || IterIndex(&it) != 1) {
return false;
}- In
Iter.c:146:
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
if (!IterMove(&it, 3) || IterIndex(&it) != 3) {
return false;
}- In
Iter.c:155:
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
size before = IterIndex(&it);
if (IterMove(&it, 4)) {
return false;- In
Iter.c:159:
return false;
}
return IterIndex(&it) == before;
}- In
Iter.c:168:
return false;
}
return IterIndex(&it) == 0;
}- In
Iter.c:175:
BufIter it = from_rev(buf, 5);
// start at pos=4
if (!IterMove(&it, 2) || IterIndex(&it) != 2) {
return false;
}- In
Iter.c:179:
}
// step backward in reverse direction (n=-1, effective +1)
if (!IterMove(&it, -1) || IterIndex(&it) != 3) {
return false;
}- In
Iter.c:189:
BufIter it = from_rev(buf, 3);
// pos=2, dir=-1, move by 3 lands on sentinel pos=-1
if (!IterMove(&it, 3) || IterIndex(&it) != (size)-1) {
return false;
}- In
Iter.c:199:
BufIter it = from_rev(buf, 3);
// pos=2, dir=-1, move by 4 would land at pos=-2 — invalid
size before = IterIndex(&it);
if (IterMove(&it, 4)) {
return false;- In
Iter.c:203:
return false;
}
return IterIndex(&it) == before;
}- In
Iter.c:209:
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
if (!IterNext(&it) || IterIndex(&it) != 1) {
return false;
}- In
Iter.c:212:
return false;
}
if (!IterNext(&it) || IterIndex(&it) != 2) {
return false;
}- In
Iter.c:215:
return false;
}
if (!IterPrev(&it) || IterIndex(&it) != 1) {
return false;
}- In
Iter.c:218:
return false;
}
if (!IterPrev(&it) || IterIndex(&it) != 0) {
return false;
}- In
StrIter.h:213:
/// TAGS: StrIter, Position, Alias
///
#define StrIterIndex(mi) IterIndex(mi)
///
Last updated on