Skip to content

MemCompare

Description

Compare memory regions. A zero byte count returns 0 without reading either pointer.

Parameters

Name Direction Description
p1 in First memory region.
p2 in Second memory region.
n in Number of bytes to compare.

Success

Returns 0 if equal, <0 if p1<p2, >0 if p1>p2.

Failure

Aborts via LOG_FATAL when n > 0 and either p1 or p2 is NULL.

Usage example (Cross-references)

Usage examples (Cross-references)
    
    __attribute__((used)) int memcmp(const void *a, const void *b, freestanding_size_t n) {
        return (int)MemCompare(a, b, (size)n);
    }
    #include <Misra/Std/Memory.h>
    
    i32 MemCompare(const void *p1, const void *p2, size n) {
        if (n == 0) {
            return 0;
                continue;
            }
            if (MemCompare(haystack + pos, needle, needle_len) == 0) {
                return haystack + pos;
            }
    
        min = StrLen(a) < StrLen(b) ? StrLen(a) : StrLen(b);
        cmp = MemCompare(StrBegin(a), StrBegin(b), min);
    
        if (cmp != 0) {
    
    static inline bool starts_with(Zstr data, size data_len, Zstr prefix, size prefix_len) {
        return data_len >= prefix_len && MemCompare(data, prefix, prefix_len) == 0;
    }
    
    static inline bool ends_with(Zstr data, size data_len, Zstr suffix, size suffix_len) {
        return data_len >= suffix_len && MemCompare(data + data_len - suffix_len, suffix, suffix_len) == 0;
    }
    
        while (i + match_len <= s->length && replaced < count) {
            if (MemCompare(s->data + i, match, match_len) == 0) {
                StrDeleteRange(s, i, match_len);
                StrInsertMany(s, replacement, replacement_len, i);
        const PeCodeViewInfo *pe_cv   = PeCodeView(&entry->pe);
        const PdbInfo        *pdb_inf = PdbInfoStream(&entry->pdb);
        if (pe_cv->age != pdb_inf->age || MemCompare(pe_cv->guid, pdb_inf->guid, 16) != 0) {
            LOG_ERROR("PdbCache: GUID/age mismatch between PE and PDB for {}", entry->module_path);
            PdbDeinit(&entry->pdb);
        if (main->build_id_size != sidecar->build_id_size)
            return false;
        return MemCompare(main->build_id, sidecar->build_id, main->build_id_size) == 0;
    }
        StrDeinit(&path);
    
        if (!MachoHasUuid(&e->dsym) || MemCompare(MachoUuid(&e->dsym), MachoUuid(&e->main), 16) != 0) {
            LOG_ERROR("MachoCache: dSYM UUID mismatch for {}", e->module_path);
            MachoDeinit(&e->dsym);
            char sep;
            if (StrIterRemainingLength(&si) > kw_len &&
                MemCompare(StrIterDataAt(&si, StrIterIndex(&si)), NS_KEYWORD, kw_len) == 0 &&
                StrIterPeekAt(&si, (i64)kw_len, &sep) && (sep == ' ' || sep == '\t')) {
                StrIterMustMove(&si, (i64)kw_len);
            return false;
        }
        if (MemCompare(BufData(&self->data), MSF_MAGIC_7, sizeof(MSF_MAGIC_7)) != 0) {
            LOG_ERROR("PDB: bad MSF magic (not 7.00)");
            return false;
    
        bool result = written == 4;
        result      = result && (MemCompare(out, bytes, sizeof(bytes)) == 0);
        result      = result && (ZstrCompare(StrBegin(&text), "cdef1234") == 0);
    
        bool result = written == 4;
        result      = result && (MemCompare(out, bytes, sizeof(bytes)) == 0);
        result      = result && (ZstrCompare(StrBegin(&text), "12345678") == 0);
        char buf[64];
        i64  got = SocketRecv(&server, buf, sizeof(buf));
        bool ok  = got == (i64)n && MemCompare(buf, payload, n) == 0;
    
        SocketClose(&server);
    
        ok = m.cputype == 0x01000007u && m.filetype == MACHO_FILE_TYPE_EXECUTE;
        ok = ok && m.has_uuid && MemCompare(m.uuid, kUuid, 16) == 0;
        ok = ok && VecLen(&m.segments) == 1;
        ok = ok && ZstrCompare(VecPtrAt(&m.segments, 0)->name, "__TEXT") == 0;
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // u64 BE
        };
        bool ok = BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        BufWriteULeb128(&b, 16384);
        const u8 expect_uleb[] = {0x00, 0x7F, 0x80, 0x01, 0x80, 0x80, 0x01};
        if (BufLength(&b) != sizeof(expect_uleb) || MemCompare(BufData(&b), expect_uleb, sizeof(expect_uleb)) != 0) {
            BufDeinit(&b);
            DefaultAllocatorDeinit(&alloc);
        BufWriteSLeb128(&b, -64);
        const u8 expect_sleb[] = {0x00, 0x7F, 0xC0, 0x00, 0x40};
        bool ok = BufLength(&b) == sizeof(expect_sleb) && MemCompare(BufData(&b), expect_sleb, sizeof(expect_sleb)) == 0;
    
        BufDeinit(&b);
        BufWriteZstr(&b, "hi");
        const u8 expect[] = {'h', 'i', 0};
        bool     ok       = BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        bool     ok       = BufAppendFmt(&b, "{<2r}{>4r}", (u16)0xCAFE, (u32)0xDEADBEEF);
        const u8 expect[] = {0x99, 0xFE, 0xCA, 0xDE, 0xAD, 0xBE, 0xEF};
        ok                = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        bool     ok       = BufWriteFmt(&b, "{<2r}", (u16)0x1234);
        const u8 expect[] = {0x34, 0x12};
        ok                = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
            0x11
        };
        ok = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
    
        // Out-of-range patch must fail and leave the buf unchanged.
        ok = ok && !BufPatchFmt(&b, BufLength(&b), "{<2r}", (u16)0);
        ok = ok && BufLength(&b) == BufLength(&snapshot);
        ok = ok && MemCompare(BufData(&b), BufData(&snapshot), BufLength(&b)) == 0;
        BufDeinit(&snapshot);
        ok = ok && pdb.info.signature == 0xdeadbeef;
        ok = ok && pdb.info.age == 0x42;
        ok = ok && MemCompare(pdb.info.guid, kGuid, 16) == 0;
    
        PdbDeinit(&pdb);
        ok = ok && pe.codeview.present;
        ok = ok && pe.codeview.age == 0x2a;
        ok = ok && MemCompare(pe.codeview.guid, kGuid, 16) == 0;
        ok = ok && pe.codeview.pdb_path && ZstrCompare(pe.codeview.pdb_path, kPdbPath) == 0;
Last updated on