⬢ DragonFlyBSD Kernel Audit
DF-5706 / fixed_driver.c
← back to finding ↓ download raw
/*
 * Fix-validation driver: differential vs naive reference on the FIXED
 * (fix.diff) instrumented copy, plus the zero-overread assertion.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>

extern unsigned long g_below_start, g_past_end, g_in;
extern unsigned long g_max_below, g_max_past, g_filtered, g_outside_granule;
void *memcchr_fixed_instr(const void *, int, size_t);

#define ASZ (1 << 20)
static unsigned char *A;

static uint64_t s_state = 0x243f6a8885a308d3ULL;
static uint64_t prng(void)
{
	s_state ^= s_state << 13; s_state ^= s_state >> 7; s_state ^= s_state << 17;
	return s_state;
}

static void *ref(const unsigned char *b, int c, size_t n)
{
	size_t i;
	for (i = 0; i < n; i++)
		if (b[i] != (unsigned char)c)
			return ((unsigned char *)(uintptr_t)(b + i));
	return (NULL);
}

static long fails, total;

static void check(unsigned char *b, int c, size_t n)
{
	void *r = memcchr_fixed_instr(b, c, n);
	void *e = ref(b, c, n);
	total++;
	if (r != e) {
		if (fails < 10)
			printf("DIFF FAIL n=%zu c=%#x off=%td got=%p want=%p\n",
			    (size_t)n, c, (ptrdiff_t)(b - A), r, e);
		fails++;
	}
}

int main(void)
{
	int ok = 1;

	A = malloc(ASZ);
	if (!A) { perror("malloc"); return 2; }
	memset(A, 0x5a, ASZ);

	{
		int off, len, mpos, ci;
		int cs[4] = { 0x00, 0xff, 0x41, 0x80 };
		for (off = 0; off < 32; off++)
		for (len = 0; len <= 96; len++)
		for (ci = 0; ci < 4; ci++)
		for (mpos = 0; mpos <= len; mpos++) {
			unsigned char *b = A + 64 + off;
			int c = cs[ci];
			size_t i;
			for (i = 0; i < (size_t)len; i++)
				b[i] = (unsigned char)c;
			b[-1] = (unsigned char)~c;
			b[len] = (unsigned char)~c;
			if (mpos < len)
				b[mpos] = (unsigned char)~c;
			check(b, c, (size_t)len);
		}
	}
	{
		long i;
		for (i = 0; i < 2000000; i++) {
			size_t off = (size_t)(prng() & 0xffff);
			size_t n = (size_t)(prng() % 8193);
			int c = (int)(prng() & 0xff);
			size_t j;
			unsigned char *b = A + 128 + off;
			if (128 + off + n + 128 > ASZ)
				n = 0;
			for (j = 0; j < n; j++)
				b[j] = (prng() & 4) ? (unsigned char)c
				    : (unsigned char)prng();
			check(b, c, n);
		}
	}
	printf("fixed differential: %ld cases, %ld failures\n", total, fails);
	printf("fixed loads: below-start=%lu past-end=%lu in-range=%lu"
	    " outside-granule=%lu done-filter-rejections=%lu\n",
	    g_below_start, g_past_end, g_in, g_outside_granule, g_filtered);

	if (fails != 0) ok = 0;
	if (g_below_start != 0 || g_past_end != 0 || g_outside_granule != 0)
		ok = 0;
	printf("RESULT: %s\n", ok ?
	    "FIX-PASS - zero loads outside [begin,begin+n), semantics exact" :
	    "FIX-FAIL");
	return ok ? 0 : 1;
}