Skip to content

IterMustMove

Description

Aborting variant of IterMove. See that macro for parameter semantics and success-state effects.

Success

Returns to the caller; the underlying IterMove succeeded.

Failure

Does not return - aborts via LOG_FATAL when the new position would be out of range.

Usage example (Cross-references)

Usage examples (Cross-references)
    /// TAGS: StrIter, Move, Must, Alias
    ///
    #define StrIterMustMove(si, n) IterMustMove((si), (n))
    
    ///
        do {                                                                                                               \
            if (!IterMove((mi), (n))) {                                                                                    \
                LOG_FATAL("IterMustMove: target position out of range");                                                   \
            }                                                                                                              \
        } while (0)
    /// TAGS: Iter, Move, Must, Abort
    ///
    #define IterMustNext(mi) IterMustMove((mi), 1)
    
    ///
    /// TAGS: Iter, Move, Must, Abort
    ///
    #define IterMustPrev(mi) IterMustMove((mi), -1)
    
    #endif // MISRA_STD_UTILITY_ITER_MOVE_H
                    return false;
                }
                IterMustMove(iter, 1);
                StrIterMustNext(&fsi);
                continue;
                    return false;
                }
                IterMustMove(iter, 1);
                StrIterMustNext(&fsi); // step over second '{'
                continue;
            // guard above; reaching here means at least `fmt_info.width` bytes remain
            // in the cursor, which is what IterMustMove consumes.
            IterMustMove(iter, fmt_info.width);
    
            // Resolve destination variable width via the reader fn pointer
            MemCopy(s.name, IterDataAt(&c, IterIndex(&c)), 8);
            s.name[8] = '\0';
            IterMustMove(&c, 8);
    
            u32 ptr_relocs, ptr_linenums;
            // 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))
                continue;
                // 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;
            }
    
            // Same bounds proof: unit_end_pos was bounded above.
            IterMustMove(&info_cur, (i64)(unit_end_pos - IterIndex(&info_cur)));
        }
                // 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;
            }
        // captured (sub-iter copy is used for CNAME/NS/PTR target decode),
        // and the rdlength bounds were already verified above.
        IterMustMove(it, (i64)rdlength);
        return true;
    }
            // 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)));
        }
            // immediately above proves the body has at least `aug_len`
            // bytes left.
            IterMustMove(body, (i64)aug_len);
        }
                    u64 id_field_off = (u64)(IterIndex(&section_cur) - 4);
                    if ((u64)id > id_field_off) {
                        IterMustMove(&section_cur, (i64)(length32 - 4));
                        continue;
                    }
    
            // Same bounds proof as above: jump past this record's body.
            IterMustMove(&section_cur, (i64)((body_pos_start + length32) - IterIndex(&section_cur)));
        }
        return true;
                // Must-precondition: the `expr_len > IterRemainingLength`
                // check above proves at least `expr_len` bytes remain.
                IterMustMove(cur, (i64)expr_len);
                return true;
            }
        // SEG64_CMD_SIZE_MIN` (checked above) reserves the 8-byte prefix
        // 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';
        MemCopy(seg.name, IterDataAt(cmd, IterIndex(cmd)), 16);
        seg.name[16] = '\0';
        IterMustMove(cmd, 16);
        u32 maxprot, initprot;
        if (!BufReadFmt(
            MemCopy(sec.section, IterDataAt(&sec_it, IterIndex(&sec_it)), 16);
            sec.section[16] = '\0';
            IterMustMove(&sec_it, 16);
            MemCopy(sec.segment, IterDataAt(&sec_it, IterIndex(&sec_it)), 16);
            sec.segment[16] = '\0';
            MemCopy(sec.segment, IterDataAt(&sec_it, IterIndex(&sec_it)), 16);
            sec.segment[16] = '\0';
            IterMustMove(&sec_it, 16);
            u32 align, reloff, nreloc, reserved1, reserved2, reserved3;
            if (!BufReadFmt(
            // check at the top of the loop body proves the cursor still has
            // SECT64_SIZE bytes left when we get here.
            IterMustMove(cmd, SECT64_SIZE);
        }
        return true;
        // Must-precondition: `IterLength >= SYMTAB_CMD_SIZE` (checked
        // above) covers the 8-byte prefix and the body.
        IterMustMove(cmd, 8); // skip cmd + cmdsize prefix
        if (!BufReadFmt(cmd, FMT_MACHO_SYMTAB_BODY_LE, ctx->symoff, ctx->nsyms, ctx->stroff, ctx->strsize)) {
            LOG_ERROR("MachO: LC_SYMTAB body truncated");
        // Must-precondition: the `IterLength >= UUID_CMD_SIZE` check above
        // 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;
        // `MH_HEADER_64_SIZE + sizeofcmds` bytes, so the header skip stays
        // inside `walker`.
        IterMustMove(&walker, MH_HEADER_64_SIZE);
        IterTruncate(&walker, ctx->sizeofcmds);
            // Must-precondition: the `cmdsize > remaining` check above
            // proves the walker has at least `cmdsize` bytes left.
            IterMustMove(&walker, cmdsize);
        }
        return true;
        // Must-precondition: `tab_end > BufLength` was checked above, so
        // `symoff <= tab_end <= BufLength` and the move stays in-bounds.
        IterMustMove(&tab, ctx->symoff);
        IterTruncate(&tab, (u64)ctx->nsyms * NLIST64_SIZE);
        for (u32 i = 0; i < ctx->nsyms; ++i) {
    
        BufIter iter = BufIterFromBuf(&self->data);
        IterMustMove(&iter, EI_NIDENT);
    
        u16 type = 0, machine = 0, ehsize = 0, phentsize = 0, phnum = 0, shentsize = 0, shnum = 0, shstrndx = 0;
        {
            BufIter iter = BufIterFromBuf(&self->data);
            IterMustMove(&iter, shoff + (u64)self->header.shstrndx * SHDR64_SIZE);
            u32 name = 0, type = 0, link = 0, info = 0;
            u64 flags = 0, addr = 0, offset = 0, size_ = 0, addralign = 0, entsize = 0;
    
        BufIter iter = BufIterFromBuf(&self->data);
        IterMustMove(&iter, shoff);
        for (u16 i = 0; i < n; ++i) {
            u32 name = 0, type = 0, link = 0, info = 0;
    
        BufIter iter = BufIterFromBuf(&self->data);
        IterMustMove(&iter, phoff);
        for (u16 i = 0; i < n; ++i) {
            u32 type = 0, flags = 0;
    
        BufIter iter = BufIterFromBuf(&self->data);
        IterMustMove(&iter, symtab->offset);
        for (u64 i = 0; i < count; ++i) {
            u32 name = 0;
        // Must-precondition: the `IterRemainingLength < count` guard above
        // 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;
                // 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
                // consumed gives us the size of this whole unit.
                // unit_end_pos was bounded above against the section end.
                IterMustMove(&section_cur, (i64)(unit_end_pos - IterIndex(&section_cur)));
                continue;
            }
            // -- `hdr.strings_start` was assigned from inside this section's
            // data window during header decode.
            IterMustMove(&str_cur, (i64)strings_start_pos);
            if (!collect_cu_strings(str_cur, &out->string_pool, &cs)) {
                cu_strings_deinit(&cs);
            // `strings_start_pos` is inside `[0, unit_end_pos]` by header
            // decode, and `prog_anchor` covers the same window.
            IterMustMove(&prog_anchor, (i64)strings_start_pos);
            if (!skip_line_program_tables(&prog_anchor)) {
                cu_strings_deinit(&cs);
            cu_strings_deinit(&cs);
            // Same bounds proof as the unsupported-version branch above.
            IterMustMove(&section_cur, (i64)(unit_end_pos - IterIndex(&section_cur)));
        }
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        IterMustMove(&it, 4);
        return true;
    }
Last updated on