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);
}- In
Memory.c:10:
#include <Misra/Std/Memory.h>
i32 MemCompare(const void *p1, const void *p2, size n) {
if (n == 0) {
return 0;- In
Zstr.c:356:
continue;
}
if (MemCompare(haystack + pos, needle, needle_len) == 0) {
return haystack + pos;
}- In
Str.c:193:
min = StrLen(a) < StrLen(b) ? StrLen(a) : StrLen(b);
cmp = MemCompare(StrBegin(a), StrBegin(b), min);
if (cmp != 0) {- In
Str.c:437:
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;
}- In
Str.c:441:
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;
}- In
Str.c:480:
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); if (main->build_id_size != sidecar->build_id_size)
return false;
return MemCompare(main->build_id, sidecar->build_id, main->build_id_size) == 0;
}- In
PdbCache.c:83:
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);- In
Dns.c:274:
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);- In
MachoCache.c:94:
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);- In
Pdb.c:147:
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;- In
File.c:466:
// rejected. A constant flags value drops O_RDONLY and/or adds O_TRUNC,
// breaking at least one of these.
ok = ok && (got == 7) && (MemCompare(buf, "read-me", 7) == 0);
ok = ok && (FileWrite(&f, "X", 1) == -1);
FileClose(&f);- In
File.c:621:
// Exact 5-byte read of the leading content.
i64 got = FileRead(&f, buf, 5);
ok = ok && (got == 5) && (MemCompare(buf, "ABCDE", 5) == 0);
FileClose(&f);- In
File.c:689:
// And reading now succeeds again from the top.
char buf2[3] = {0};
ok = ok && (FileRead(&f, buf2, 3) == 3) && (MemCompare(buf2, "abc", 3) == 0);
FileClose(&f);- In
File.c:836:
FileClose(&r);
ok = ok && (got == (i64)N) && (BufLength(&dst) == (size)N) && (MemCompare(BufData(&dst), BufData(&src), N) == 0);
BufDeinit(&src);- In
File.c:1005:
ok = ok && (FileSeek(&f, 0, FILE_SEEK_SET) == 0);
char buf[10] = {0};
ok = ok && (FileRead(&f, buf, 9) == 9) && (MemCompare(buf, "temp-data", 9) == 0);
FileClose(&f);- In
Buf.c:44:
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);- In
Buf.c:58:
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);- In
Buf.c:70:
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);- In
Buf.c:82:
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);- In
Buf.c:158:
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);- In
Buf.c:172:
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);- In
Buf.c:200:
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.
- In
Buf.c:207:
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);- In
Convert.c:123:
bool result = written == 4;
result = result && (MemCompare(out, bytes, sizeof(bytes)) == 0);
result = result && (ZstrCompare(StrBegin(&text), "cdef1234") == 0);- In
Convert.c:144:
bool result = written == 4;
result = result && (MemCompare(out, bytes, sizeof(bytes)) == 0);
result = result && (ZstrCompare(StrBegin(&text), "12345678") == 0);- In
Convert.c:1118:
bool result = (written == 2);
result = result && (MemCompare(out, expect, 2) == 0);
IntDeinit(&value);- In
Convert.c:1165:
bool result = (written == 2);
result = result && (MemCompare(out, expect, 2) == 0);
IntDeinit(&value);- In
Write.c:3582:
bool ok = BufAppendFmt(&b, "{<1r}", (u8)0x7E);
const u8 expect[] = {0x7E};
ok = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
BufDeinit(&b);
DefaultAllocatorDeinit(&alloc);- In
Write.c:3598:
bool ok = BufAppendFmt(&b, "{<8r}", (i64)0x0102030405060708ll);
const u8 expect[] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
ok = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
BufDeinit(&b);
DefaultAllocatorDeinit(&alloc);- In
Write.c:3616:
bool ok = BufAppendFmt(&b, "{<8r}", in.f);
const u8 expect[] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
ok = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
BufDeinit(&b);
DefaultAllocatorDeinit(&alloc);- In
Socket.c:81:
char buf[64];
i64 got = SocketRecv(&server, buf, sizeof(buf));
bool ok = got == (i64)n && MemCompare(buf, payload, n) == 0;
SocketClose(&server);- In
Socket.c:1186:
char buf1[64];
i64 g1 = SocketRecv(&server, buf1, sizeof(buf1));
ok = ok && g1 == (i64)n1 && MemCompare(buf1, c2s, n1) == 0;
// server -> client (different payload + length so a swapped fd or a
- In
Socket.c:1195:
char buf2[64];
i64 g2 = SocketRecv(&client, buf2, sizeof(buf2));
ok = ok && g2 == (i64)n2 && MemCompare(buf2, s2c, n2) == 0;
SocketClose(&server);- In
Socket.c:1369:
char buf[32];
i64 got = SocketRecv(&server, buf, sizeof(buf));
ok = ok && got == (i64)n && MemCompare(buf, payload, n) == 0;
SocketClose(&server);- In
Socket.c:1407:
char buf[32];
i64 got = SocketRecv(&server, buf, sizeof(buf));
ok = ok && got == (i64)n && MemCompare(buf, payload, n) == 0;
SocketClose(&server);- In
Socket.c:1450:
char buf[16];
i64 got = SocketRecv(&server, buf, sizeof(buf));
ok = ok && got == (i64)n && MemCompare(buf, payload, n) == 0;
SocketClose(&server);- In
Pe.c:499:
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;- In
Pe.c:865:
}
bool ok = pe.codeview.present == true; // L494 present=true
ok = ok && MemCompare(pe.codeview.guid, kGuid, 16) == 0;
ok = ok && pe.codeview.age == CV_AGE;
ok = ok && pe.codeview.pdb_path && ZstrCompare(pe.codeview.pdb_path, kPdbPath) == 0;- In
Pe.c:1049:
return false;
}
bool ok = pe.codeview.present == true && pe.codeview.age == CV_AGE && MemCompare(pe.codeview.guid, kGuid, 16) == 0;
PeDeinit(&pe);
DefaultAllocatorDeinit(&alloc);- In
Pe.c:1069:
return false;
}
bool ok = pe.codeview.present == true && pe.codeview.age == CV_AGE && MemCompare(pe.codeview.guid, kGuid, 16) == 0;
PeDeinit(&pe);
DefaultAllocatorDeinit(&alloc);- In
Pe.c:1146:
return false;
}
bool ok = pe.codeview.present == true && pe.codeview.age == CV_AGE && MemCompare(pe.codeview.guid, kGuid, 16) == 0;
PeDeinit(&pe);
DefaultAllocatorDeinit(&alloc);- In
Pe.c:1242:
return false;
}
bool ok = pe.codeview.present == true && pe.codeview.age == CV_AGE && MemCompare(pe.codeview.guid, kGuid, 16) == 0;
PeDeinit(&pe);
DefaultAllocatorDeinit(&alloc);- In
Pdb.c:113:
ok = ok && pdb.info.signature == 0xdeadbeef;
ok = ok && pdb.info.age == 0x42;
ok = ok && MemCompare(pdb.info.guid, kGuid, 16) == 0;
PdbDeinit(&pdb);- In
Pdb.c:2281:
ok = ok && pi->signature == 0x05060708;
ok = ok && pi->age == 0x090A0B0C;
ok = ok && MemCompare(pi->guid, kGuid, 16) == 0;
PdbDeinit(&pdb);- In
Pdb.c:2371:
}
ok = pdb.num_streams == 2 && pdb.info.version == 20040203 && pdb.info.age == 0x42 &&
MemCompare(pdb.info.guid, kGuid, 16) == 0;
PdbDeinit(&pdb);- In
MachO.c:359:
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;- In
MachO.c:680:
Macho m;
bool ok = open_blob(&m, b, BUF, &alloc);
ok = ok && m.has_uuid && MemCompare(m.uuid, kUuid, 16) == 0;
if (ok)
MachoDeinit(&m);- In
MachO.c:1551:
// Canonical-true check: real code stores exactly `true` (== 1); the
// mutant stores 42, so `== true` is false under the mutation.
ok = ok && m.has_uuid == true && MemCompare(m.uuid, kUuid, 16) == 0;
if (ok)
MachoDeinit(&m);- In
Elf.c:717:
bool ok = elf.build_id != NULL && elf.build_id_size == BUILD_ID_LEN &&
MemCompare(elf.build_id, kBuildId, BUILD_ID_LEN) == 0;
ok = ok && elf.debuglink_name != NULL && ZstrCompare(elf.debuglink_name, "foo.debug") == 0 &&- In
Elf.c:1925:
}
bool ok =
elf.build_id != NULL && elf.build_id_size == sizeof(desc) && MemCompare(elf.build_id, desc, sizeof(desc)) == 0;
ElfDeinit(&elf);
DefaultAllocatorDeinit(&alloc);- In
Elf.c:2286:
}
bool ok = elf.build_id != NULL && elf.build_id_size == BUILD_ID_LEN &&
MemCompare(elf.build_id, kBuildId, BUILD_ID_LEN) == 0;
ok = ok && elf.debuglink_name != NULL && ZstrCompare(elf.debuglink_name, "foo.debug") == 0 &&
elf.debuglink_crc == DEBUGLINK_CRC; Zstr msg_want = "Hello, \"World\"!";
Zstr data_want = "line1\nline2\ttab";
if (StrLen(&obj.path) != ZstrLen(path_want) || MemCompare(StrBegin(&obj.path), path_want, StrLen(&obj.path)) != 0) {
WriteFmtLn("[DEBUG] Special characters FAILED: path content wrong");
success = false; }
if (StrLen(&obj.message) != ZstrLen(msg_want) ||
MemCompare(StrBegin(&obj.message), msg_want, StrLen(&obj.message)) != 0) {
WriteFmtLn("[DEBUG] Special characters FAILED: message content wrong");
success = false; success = false;
}
if (StrLen(&obj.data) != ZstrLen(data_want) || MemCompare(StrBegin(&obj.data), data_want, StrLen(&obj.data)) != 0) {
WriteFmtLn("[DEBUG] Special characters FAILED: data content wrong");
success = false; success = false;
}
if (StrLen(&out) != 5 || MemCompare(StrBegin(&out), "plain", 5) != 0) {
WriteFmtLn("[DEBUG] JReadString decoded plain string wrong: len={}", StrLen(&out));
success = false;
Last updated on