Replace mem_is_zero() with membcmp() and update call sites
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-arm32 (push) Waiting to run
Build / build-win (push) Waiting to run
Build / build-freebsd (push) Waiting to run
Build / build-musl (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run

This commit is contained in:
Andrea Mazzoleni 2026-09-10 18:36:50 +02:00
parent 17838874bd
commit 8c039cc72d
3 changed files with 37 additions and 29 deletions

View file

@ -342,7 +342,7 @@ static int block_data_cmp(struct snapraid_state* state, int rehash, struct snapr
* but also makes the canonical-block invariant explicit.
*/
if (pos_size < state->block_size) {
if (!mem_is_zero(buffer + pos_size, state->block_size - pos_size)) {
if (membcmp(buffer + pos_size, 0, state->block_size - pos_size) != 0) {
return -1;
}
}
@ -1036,7 +1036,7 @@ static int repair(struct snapraid_state* state, int rehash, block_off_t pos, uns
* A zero candidate is ambiguous because OLD and CURRENT
* may legitimately contain the same zero block.
*/
if (!mem_is_zero(buffer[failed[j].index], state->block_size))
if (membcmp(buffer[failed[j].index], 0, state->block_size) != 0)
current_generation_proven = 1;
} else {
unsigned hash_kind;

View file

@ -2151,19 +2151,36 @@ static void test_misc(int argc, char* argv[])
unsigned zi, zj;
memset(zbuf, 0, sizeof(zbuf));
assert(mem_is_zero(zbuf, 0) != 0);
assert(membcmp(zbuf, 0, 0) == 0);
for (zi = 0; zi < sizeof(zbuf); ++zi) {
for (zj = zi; zj <= sizeof(zbuf); ++zj) {
assert(mem_is_zero(zbuf + zi, zj - zi) != 0);
assert(membcmp(zbuf + zi, 0, zj - zi) == 0);
}
}
for (zi = 0; zi < sizeof(zbuf); ++zi) {
zbuf[zi] = 1;
assert(mem_is_zero(zbuf, sizeof(zbuf)) == 0);
assert(membcmp(zbuf, 0, sizeof(zbuf)) > 0);
zbuf[zi] = 0;
}
memset(zbuf, 1, sizeof(zbuf));
assert(membcmp(zbuf, 1, 0) == 0);
for (zi = 0; zi < sizeof(zbuf); ++zi) {
for (zj = zi; zj <= sizeof(zbuf); ++zj) {
assert(membcmp(zbuf + zi, 1, zj - zi) == 0);
}
}
for (zi = 0; zi < sizeof(zbuf); ++zi) {
zbuf[zi] = 0;
assert(membcmp(zbuf, 1, sizeof(zbuf)) < 0);
zbuf[zi] = 2;
assert(membcmp(zbuf, 1, sizeof(zbuf)) > 0);
zbuf[zi] = 1;
}
}
for (i = 2; i < argc; ++i) {

View file

@ -39,34 +39,25 @@ void** malloc_nofail_vector_direct(int n, size_t size, void** freeptr);
void mtest_vector(int n, size_t size, void** vv);
/**
* Return !=0 if the memory region is completely filled with zeros.
* Compare memory against a repeated byte value.
*
* Return <0 if ptr is less than value, 0 if equal, >0 if greater.
*/
static inline int mem_is_zero(const void* ptr, size_t size)
static __always_inline int membcmp(const void* ptr, uint8_t value, size_t size)
{
const unsigned char* p = ptr;
const uint8_t* p = ptr;
while (size != 0 && ((uintptr_t)p % sizeof(size_t)) != 0) {
if (*p != 0)
return 0;
++p;
--size;
}
if (size == 0)
return 0;
if (p[0] != value)
return (int)p[0] - (int)value;
while (size >= sizeof(size_t)) {
if (*(const size_t*)p != 0)
return 0;
p += sizeof(size_t);
size -= sizeof(size_t);
}
while (size != 0) {
if (*p != 0)
return 0;
++p;
--size;
}
return 1;
/*
* If the buffer contains value up to index k-1, then at offset k-1
* memcmp compares (p + 1)[k - 1] = p[k] against p[k - 1] = value.
* The first differing adjacent pair yields the exact sign (p[k] - value).
*/
return memcmp(p + 1, p, size - 1);
}
/****************************************************************************/