Skip to content

BufReadFmt

Description

Read raw bytes from the cursor iter according to fmtstr. Only {<Nr} (LE) and {>Nr} (BE) directives with N in {1, 2, 4, 8} are accepted; the destination variable’s natural width must match the spec width.

Success

Returns true; iter advances past the consumed bytes and every destination variable is filled.

Failure

Returns false on format-parse error or cursor overflow. iter and destination variables may be left partially updated by directives that ran before the failure.

Usage example (Cross-references)

Usage examples (Cross-references)
        u16 machine, num_sec, size_opt, chars;
        u32 timestamp, sym_ptr, num_sym;
        if (!BufReadFmt(&c, FMT_PE_FILE_HEADER_LE, machine, num_sec, timestamp, sym_ptr, num_sym, size_opt, chars)) {
            LOG_ERROR("PE: file header truncated");
            return false;
        if (is64) {
            u64 stack_res, stack_com, heap_res, heap_com;
            if (!BufReadFmt(
                    &c,
                    FMT_PE_OPT_HDR_PE32PLUS_LE,
        } else {
            u32 base_of_data, image_base32, stack_res, stack_com, heap_res, heap_com;
            if (!BufReadFmt(
                    &c,
                    FMT_PE_OPT_HDR_PE32_LE,
            u32 ptr_relocs, ptr_linenums;
            u16 num_relocs, num_linenums;
            if (!BufReadFmt(
                    &c,
                    FMT_PE_SECTION_HEADER_LE,
            u32     charac, ts, type, sz, raddr, rptr;
            u16     ver_maj, ver_min;
            if (!BufReadFmt(&c, FMT_PE_DEBUG_DIR_LE, charac, ts, ver_maj, ver_min, type, sz, raddr, rptr))
                return;
            (void)charac;
            u8  addr_size;
            // DWARF v4 CU header tail after unit_length: 2 + 4 + 1 bytes.
            if (!BufReadFmt(&info_cur, "{<2r}{<4r}{<1r}", version, abbrev_offset, addr_size)) {
                ok = false;
                break;
        u16 type_bits, class_bits, rdlength;
        u32 ttl;
        if (!BufReadFmt(it, "{>2r}{>2r}{>4r}{>2r}", type_bits, class_bits, ttl, rdlength)) {
            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;
        }
            StrDeinit(&dummy);
            u16 qtype, qclass;
            if (!BufReadFmt(&it, "{>2r}{>2r}", qtype, qclass)) {
                return false;
            }
        BufIter sb = BufIterFromMemory(BufData(&self->data) + 32, BufLength(&self->data) - 32);
        u32     free_blk, num_blocks, unknown;
        if (!BufReadFmt(
                &sb,
                FMT_PDB_SUPERBLOCK_LE,
                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,
                    FMT_PDB_DBI_HEADER_LE,
                u32     flags, offset;
                u16     segment;
                if (!BufReadFmt(&body, FMT_S_PUB32_PREFIX_LE, flags, offset, segment)) {
                    cur = next;
                    continue;
        // "TZif" magic matched inline; a non-TZif file fails the read here.
        u8 ver = 0;
        if (!BufReadFmt(it, "TZif{>1r}", ver))
            return false;
        if (!IterMove(it, 15)) // reserved
            return false;
    
        if (!BufReadFmt(it, FMT_TZIF_COUNTS_BE, h->isutcnt, h->isstdcnt, h->leapcnt, h->timecnt, h->typecnt, h->charcnt))
            return false;
        h->version = ver;
            i64 t = 0;
            if (time_width == 8) {
                if (!BufReadFmt(it, "{>8r}", t))
                    return false;
            } else {
            } else {
                i32 t32 = 0;
                if (!BufReadFmt(it, "{>4r}", t32))
                    return false;
                t = t32;
            if (best > 0 && !IterMove(it, best))
                return false;
            if (!BufReadFmt(it, "{>1r}", chosen))
                return false;
            have_chosen = true;
            i32 utoff = 0;
            u8  isdst = 0, desigidx = 0;
            if (!BufReadFmt(it, FMT_TZIF_TTINFO_BE, utoff, isdst, desigidx))
                return false;
            if (have_chosen && i == (u32)chosen) {
        BufIter c = BufIterFromBuf(&m->data);
        u32     magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags, reserved;
        if (!BufReadFmt(
                &c,
                FMT_MACHO_HEADER_LE,
        IterMustMove(cmd, 16);
        u32 maxprot, initprot;
        if (!BufReadFmt(
                cmd,
                FMT_MACHO_SEGMENT64_BODY_LE,
            IterMustMove(&sec_it, 16);
            u32 align, reloff, nreloc, reserved1, reserved2, reserved3;
            if (!BufReadFmt(
                    &sec_it,
                    FMT_MACHO_SECTION64_BODY_LE,
        // 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");
            return false;
            BufIter prefix = IterCarve(&walker, 8);
            u32     cmd, cmdsize;
            if (!BufReadFmt(&prefix, FMT_MACHO_LC_PREFIX_LE, cmd, cmdsize)) {
                LOG_ERROR("MachO: load command prefix truncated at {}", i);
                return false;
            u16 n_desc;
            u64 n_value;
            if (!BufReadFmt(&tab, FMT_MACHO_NLIST64_LE, n_strx, n_type, n_sect, n_desc, n_value)) {
                LOG_ERROR("MachO: nlist_64 truncated at index {}", i);
                return false;
        u64 entry = 0, phoff = 0, shoff = 0;
    
        BufReadFmt(
            &iter,
            FMT_EHDR64_LE,
            u32 name = 0, type = 0, link = 0, info = 0;
            u64 flags = 0, addr = 0, offset = 0, size_ = 0, addralign = 0, entsize = 0;
            BufReadFmt(&iter, FMT_SHDR64_LE, name, type, flags, addr, offset, size_, link, info, addralign, entsize);
            shstr_off  = offset;
            shstr_size = size_;
            u64 flags = 0, addr = 0, offset = 0, size_ = 0, addralign = 0, entsize = 0;
    
            BufReadFmt(&iter, FMT_SHDR64_LE, name, type, flags, addr, offset, size_, link, info, addralign, entsize);
    
            ElfSection s;
            u64 offset = 0, vaddr = 0, paddr = 0, filesz = 0, memsz = 0, align = 0;
    
            BufReadFmt(&iter, FMT_PHDR64_LE, type, flags, offset, vaddr, paddr, filesz, memsz, align);
            (void)paddr; // physical address is meaningless for a hosted process
            u64 value = 0, size_ = 0;
    
            BufReadFmt(&iter, FMT_SYM64_LE, name, info, other, shndx, value, size_);
    
            ElfSymbol s;
        u8 raw_lb      = 0;
        if (version >= 4) {
            if (!BufReadFmt(
                    cur,
                    FMT_DWARF_LINE_HDR_V4_TAIL_LE,
            }
        } else {
            if (!BufReadFmt(
                    cur,
                    FMT_DWARF_LINE_HDR_V3_TAIL_LE,
        u32     v32;
        u64     v64;
        bool    ok = BufReadFmt(&it, "{<2r}{>4r}{<8r}", v16, v32, v64);
        ok         = ok && v16 == 0x1234 && v32 == 0xDEADBEEF && v64 == 0x0102030405060708ull;
        ok         = ok && IterRemainingLength(&it) == 0;
        u16     v16   = 0;
        u32     v32   = 0;
        bool    ok    = !BufReadFmt(&it, "{<2r}{<4r}", v16, v32);
        // Atomic rollback: pos restored, output vars left as initialized.
        ok = ok && it.pos == entry && v32 == 0;
            u16     v16   = 0;
            u64     v64   = 0;
            bool    rd_ok = BufReadFmt(&it, "{<2r}{>8r}", v16, v64);
            ok            = ok && rd_ok && (v16 == 0x1234) && (v64 == 0x0102030405060708ULL);
        }
            BufIter it  = BufIterFromBuf(&b);
            u8      ver = 0;
            ok          = ok && BufReadFmt(&it, "TZif{>1r}", ver) && (ver == '2');
        }
            BufIter it  = BufIterFromBuf(&b);
            u8      ver = 0xAB;
            bool    rd  = BufReadFmt(&it, "TZig{>1r}", ver);
            ok          = ok && !rd && (ver == 0xAB) && (IterRemainingLength(&it) == 5);
        }
        BufIter it = BufIterFromBuf(&b);
        u8      v  = 0;
        ok         = ok && BufReadFmt(&it, "{​{{>1r}", v) && (v == 0x41);
    
        BufDeinit(&b);
            BufIter it = BufIterFromBuf(&b);
            u8      q  = 0;
            ok         = ok && BufReadFmt(&it, "{>1r}Z", q) && (q == 'Q');
        }
        // Same, but the trailing literal is an escaped '{'.
            BufIter it = BufIterFromBuf(&b);
            u8      q  = 0;
            ok         = ok && BufReadFmt(&it, "{>1r}{​{", q) && (q == 'Q');
        }
        BufIter it = BufIterFromBuf(&b);
        u8      v8 = 0;
        bool    rd = BufReadFmt(&it, "{<1r}", v8);
        ok         = ok && rd && (v8 == 0x05);
        BufIter it  = BufIterFromBuf(&b);
        u32     v32 = 0;
        bool    rd  = BufReadFmt(&it, "{<4r}", v32);
        ok          = ok && rd && (v32 == 0xDEADBEEF);
        BufIter it  = BufIterFromBuf(&b);
        u64     v64 = 0;
        bool    rd  = BufReadFmt(&it, "{>8r}", v64);
        ok          = ok && rd && (v64 == 0x0102030405060708ULL);
        BufIter it  = BufIterFromBuf(&b);
        i64     v64 = 0;
        bool    rd  = BufReadFmt(&it, "{<8r}", v64);
        ok          = ok && rd && (v64 == -1234567890123LL);
        BufIter it  = BufIterFromBuf(&b);
        u16     v16 = 0;
        BufReadFmt(&it, "{2}", v16); // real: LOG_FATAL (non-raw). mutant: returns.
    
        BufDeinit(&b);
        BufIter it  = BufIterFromBuf(&b);
        u64     v64 = 0;
        ok          = ok && BufReadFmt(&it, "{>8r}", v64);
        ok          = ok && (v64 == 0x0102030405060708ULL);
        BufIter it    = BufIterFromBuf(&b);
        u16     v16   = 0;
        bool    rd_ok = BufReadFmt(&it, "{^2r}", v16);
        ok            = ok && rd_ok && (v16 == 0x1234);
        BufIter it = BufIterFromBuf(&b);
        u8      v8 = 0;
        BufReadFmt(&it, "{<1r}{<1r}", v8);                 // 2 fields, 1 arg -> abort
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        u16     a              = 0;
        u32     c              = 0;
        ok                     = ok && BufReadFmt(&it, "{<2r}{>4r}", a, c) && a == 0x1234 && c == 0xAABBCCDD;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        BufIter it    = BufIterFromBuf(&b);
        u32     v32   = 0;
        bool    rd_ok = BufReadFmt(&it, "{>4r}", v32);
        ok            = ok && rd_ok && (v32 == 0x12345678u);
        BufIter it    = BufIterFromBuf(&b);
        u32     v32   = 0;
        bool    rd_ok = BufReadFmt(&it, "{<4r}", v32);
        ok            = ok && rd_ok && (v32 == 0x12345678u);
        BufIter it    = BufIterFromBuf(&b);
        u32     v32   = 0;
        bool    rd_ok = BufReadFmt(&it, "{<4r}", v32);
        ok            = ok && rd_ok && (v32 == 0x78563412u);
        BufIter it    = BufIterFromBuf(&b);
        u32     v32   = 0;
        bool    rd_ok = BufReadFmt(&it, "{^4r}", v32);
        ok            = ok && rd_ok && (v32 == 0xAABBCCDDu);
        BufIter it    = BufIterFromBuf(&b);
        u64     v64   = 0;
        bool    rd_ok = BufReadFmt(&it, "{<8r}", v64);
        ok            = ok && rd_ok && (v64 == expected);
        BufIter it    = BufIterFromBuf(&b);
        u64     v64   = 0;
        bool    rd_ok = BufReadFmt(&it, "{<8r}", v64);
        ok            = ok && rd_ok && (v64 == expected);
        BufIter it    = BufIterFromBuf(&b);
        u64     v64   = 0;
        bool    rd_ok = BufReadFmt(&it, "{^8r}", v64);
        ok            = ok && rd_ok && (v64 == expected);
        BufIter it  = BufIterFromBuf(&b);
        u8      out = 0;
        ok          = ok && BufReadFmt(&it, "{<1r}", out) && (out == 0xAB);
    
        BufDeinit(&b);
        BufIter          it    = BufIterFromBuf(&b);
        u16              v     = 0;
        ok                     = ok && BufReadFmt(&it, "{<2r}", v) && (v == 0xBEEF);
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        bool    ok = BufWriteFmt(&b, "{<8r}", (u64)0x0102030405060708ULL);
        BufIter it = BufIterFromBuf(&b);
        ok         = ok && BufReadFmt(&it, "{<8r}", got.f) && (got.u == 0x0102030405060708ULL);
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
Last updated on