kasantest: Add performance testing for Kasan, including pile insertion testing and algorithm testing

Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
This commit is contained in:
wangmingrong1 2024-09-06 15:56:36 +08:00 committed by Xiang Xiao
parent f2c21b11d8
commit 7c94d13be4
3 changed files with 124 additions and 22 deletions

View File

@ -8,3 +8,23 @@ config TESTING_KASAN
default n default n
---help--- ---help---
Enable the KASan validity test Enable the KASan validity test
if TESTING_KASAN
config TESTING_KASAN_PRIORITY
int "KASan test priority"
default 101
config TESTING_KASAN_STACKSIZE
int "KASan test stack size"
default 8192
config TESTING_KASAN_PERF_HEAP_SIZE
int "KASan test heap size"
default 1024000
config TESTING_KASAN_PERF_CYCLES
int "KASan test performance cycles"
default 4096
endif

View File

@ -24,11 +24,12 @@ include $(APPDIR)/Make.defs
MAINSRC = kasantest.c MAINSRC = kasantest.c
PROGNAME = kasantest PROGNAME = kasantest
PRIORITY = SCHED_PRIORITY_DEFAULT PRIORITY = $(CONFIG_TESTING_KASAN_PRIORITY)
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE) STACKSIZE = $(CONFIG_TESTING_KASAN_STACKSIZE)
CFLAGS += -Wno-error -Wno-use-after-free CFLAGS += -Wno-error -Wno-use-after-free
CFLAGS += -Wno-array-bounds -Wno-free-nonheap-object CFLAGS += -Wno-array-bounds -Wno-free-nonheap-object
CFLAGS += -Wno-stringop-overflow CFLAGS += -Wno-stringop-overflow
CFLAGS += "-O0"
include $(APPDIR)/Application.mk include $(APPDIR)/Application.mk

View File

@ -28,9 +28,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h>
#include <syslog.h> #include <syslog.h>
#include <time.h>
#include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -45,6 +46,7 @@
typedef struct testcase_s typedef struct testcase_s
{ {
bool (*func)(FAR struct mm_heap_s *heap, size_t size); bool (*func)(FAR struct mm_heap_s *heap, size_t size);
bool is_auto;
FAR const char *name; FAR const char *name;
} testcase_t; } testcase_t;
@ -71,6 +73,8 @@ static bool test_heap_unpoison(FAR struct mm_heap_s *heap, size_t size);
static bool test_heap_memset(FAR struct mm_heap_s *heap, size_t size); static bool test_heap_memset(FAR struct mm_heap_s *heap, size_t size);
static bool test_heap_memcpy(FAR struct mm_heap_s *heap, size_t size); static bool test_heap_memcpy(FAR struct mm_heap_s *heap, size_t size);
static bool test_heap_memmove(FAR struct mm_heap_s *heap, size_t size); static bool test_heap_memmove(FAR struct mm_heap_s *heap, size_t size);
static bool test_insert_perf(FAR struct mm_heap_s *heap, size_t size);
static bool test_algorithm_perf(FAR struct mm_heap_s *heap, size_t size);
#ifdef CONFIG_MM_KASAN_GLOBAL #ifdef CONFIG_MM_KASAN_GLOBAL
static bool test_global_underflow(FAR struct mm_heap_s *heap, size_t size); static bool test_global_underflow(FAR struct mm_heap_s *heap, size_t size);
@ -83,23 +87,25 @@ static bool test_global_overflow(FAR struct mm_heap_s *heap, size_t size);
const static testcase_t g_kasan_test[] = const static testcase_t g_kasan_test[] =
{ {
{test_heap_underflow, "heap underflow"}, {test_heap_underflow, true, "heap underflow"},
{test_heap_overflow, "heap overflow"}, {test_heap_overflow, true, "heap overflow"},
{test_heap_use_after_free, "heap use after free"}, {test_heap_use_after_free, true, "heap use after free"},
{test_heap_invalid_free, "heap inval free"}, {test_heap_invalid_free, true, "heap inval free"},
{test_heap_double_free, "test heap double free"}, {test_heap_double_free, true, "test heap double free"},
{test_heap_poison, "heap poison"}, {test_heap_poison, true, "heap poison"},
{test_heap_unpoison, "heap unpoison"}, {test_heap_unpoison, true, "heap unpoison"},
{test_heap_memset, "heap memset"}, {test_heap_memset, true, "heap memset"},
{test_heap_memcpy, "heap memcpy"}, {test_heap_memcpy, true, "heap memcpy"},
{test_heap_memmove, "heap memmove"}, {test_heap_memmove, true, "heap memmove"},
{test_insert_perf, false, "Kasan insert performance testing"},
{test_algorithm_perf, false, "Kasan algorithm performance testing"},
#ifdef CONFIG_MM_KASAN_GLOBAL #ifdef CONFIG_MM_KASAN_GLOBAL
{test_global_underflow, "globals underflow"}, {test_global_underflow, true, "globals underflow"},
{test_global_overflow, "globals overflow"}, {test_global_overflow, true, "globals overflow"},
#endif #endif
}; };
static char g_kasan_heap[65536] aligned_data(8); static char g_kasan_heap[10240] aligned_data(8);
#ifdef CONFIG_MM_KASAN_GLOBAL #ifdef CONFIG_MM_KASAN_GLOBAL
static char g_kasan_globals[32]; static char g_kasan_globals[32];
@ -122,6 +128,20 @@ static void error_handler(void)
} }
} }
static void timespec_sub(struct timespec *dest,
struct timespec *ts1,
struct timespec *ts2)
{
dest->tv_sec = ts1->tv_sec - ts2->tv_sec;
dest->tv_nsec = ts1->tv_nsec - ts2->tv_nsec;
if (dest->tv_nsec < 0)
{
dest->tv_nsec += 1000000000;
dest->tv_sec -= 1;
}
}
static bool test_heap_underflow(FAR struct mm_heap_s *heap, size_t size) static bool test_heap_underflow(FAR struct mm_heap_s *heap, size_t size)
{ {
FAR uint8_t *mem = mm_malloc(heap, size); FAR uint8_t *mem = mm_malloc(heap, size);
@ -223,6 +243,54 @@ static bool test_heap_memmove(FAR struct mm_heap_s *heap, size_t size)
return false; return false;
} }
static bool test_insert_perf(FAR struct mm_heap_s *heap, size_t size)
{
int num = 0;
char value;
char *p;
int i;
p = (char *)malloc(CONFIG_TESTING_KASAN_PERF_HEAP_SIZE);
if (!p)
{
printf("Failed to allocate memory for performance testing\n");
return false;
}
do
{
value = num % INT8_MAX;
for (i = 0; i < CONFIG_TESTING_KASAN_PERF_HEAP_SIZE; i++)
{
p[i] = value;
}
}
while (num++ < CONFIG_TESTING_KASAN_PERF_CYCLES);
return true;
}
static bool test_algorithm_perf(FAR struct mm_heap_s *heap, size_t size)
{
int num = 0;
char *p;
p = (char *)malloc(CONFIG_TESTING_KASAN_PERF_HEAP_SIZE);
if (!p)
{
printf("Failed to allocate memory for performance testing\n");
return false;
}
do
{
memset(p, num % INT8_MAX, CONFIG_TESTING_KASAN_PERF_HEAP_SIZE);
}
while (num++ < CONFIG_TESTING_KASAN_PERF_CYCLES);
return true;
}
#ifdef CONFIG_MM_KASAN_GLOBAL #ifdef CONFIG_MM_KASAN_GLOBAL
static bool test_global_underflow(FAR struct mm_heap_s *heap, size_t size) static bool test_global_underflow(FAR struct mm_heap_s *heap, size_t size)
{ {
@ -239,7 +307,7 @@ static bool test_global_overflow(FAR struct mm_heap_s *heap, size_t size)
static int run_test(FAR const testcase_t *test) static int run_test(FAR const testcase_t *test)
{ {
size_t heap_size = 65536; size_t heap_size = sizeof(g_kasan_heap);
FAR char *argv[3]; FAR char *argv[3];
FAR run_t *run; FAR run_t *run;
int status; int status;
@ -273,11 +341,11 @@ static int run_test(FAR const testcase_t *test)
waitpid(pid, &status, 0); waitpid(pid, &status, 0);
if (status == 0) if (status == 0)
{ {
printf("KASan test: %s, size: %ld FAIL\n", test->name, run->size); printf("KASan test: %s, size: %zu FAIL\n", test->name, run->size);
} }
else else
{ {
printf("KASan test: %s, size: %ld PASS\n", test->name, run->size); printf("KASan test: %s, size: %zu PASS\n", test->name, run->size);
} }
mm_uninitialize(run->heap); mm_uninitialize(run->heap);
@ -287,7 +355,11 @@ static int run_test(FAR const testcase_t *test)
static int run_testcase(int argc, FAR char *argv[]) static int run_testcase(int argc, FAR char *argv[])
{ {
uintptr_t index = strtoul(argv[1], NULL, 0); uintptr_t index = strtoul(argv[1], NULL, 0);
struct timespec result;
struct timespec start;
struct timespec end;
FAR run_t *run; FAR run_t *run;
int ret;
/* Pass in the number to run the specified case, /* Pass in the number to run the specified case,
* and the string of the number will not be very long * and the string of the number will not be very long
@ -311,8 +383,17 @@ static int run_testcase(int argc, FAR char *argv[])
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
run = (FAR run_t *)index; run = (FAR run_t *)(uintptr_t)strtoul(argv[1], NULL, 16);
return run->testcase->func(run->heap, run->size); clock_gettime(CLOCK_MONOTONIC, &start);
ret = run->testcase->func(run->heap, run->size);
clock_gettime(CLOCK_MONOTONIC, &end);
timespec_sub(&result, &end, &start);
printf("%s spending %ld.%lds\n", run->testcase->name,
result.tv_sec,
result.tv_nsec);
return ret;
} }
/**************************************************************************** /****************************************************************************
@ -326,7 +407,7 @@ int main(int argc, FAR char *argv[])
size_t j; size_t j;
for (j = 0; j < nitems(g_kasan_test); j++) for (j = 0; j < nitems(g_kasan_test); j++)
{ {
if (run_test(&g_kasan_test[j]) < 0) if (g_kasan_test[j].is_auto && run_test(&g_kasan_test[j]) < 0)
{ {
return EXIT_FAILURE; return EXIT_FAILURE;
} }