Skip to content

Commit

Permalink
Add test for sets struct domain for #716.
Browse files Browse the repository at this point in the history
  • Loading branch information
jerhard committed Dec 1, 2022
1 parent 23bbd8f commit 0161b64
Show file tree
Hide file tree
Showing 2 changed files with 276 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
// PARAM: --set ana.malloc.wrappers '["Malloc", "Realloc", "Malloc2", "Realloc2", "ARR_CreateInstance", "realloc_array", "ARR_GetNewElement"]' --set ana.base.structs.domain sets --disable sem.unknown_function.spawn --disable sem.unknown_function.invalidate.globals
// extracted from chrony
#include <stdlib.h>
#include <assert.h>
#include <pthread.h>

// memory.c

void *
Malloc(size_t size)
{
void *r;

r = malloc(size);

return r;
}

void *
Realloc(void *ptr, size_t size)
{
void *r;

r = realloc(ptr, size);

return r;
}

static size_t
get_array_size(size_t nmemb, size_t size)
{
size_t array_size;

array_size = nmemb * size;

return array_size;
}

void *
Realloc2(void *ptr, size_t nmemb, size_t size)
{
return Realloc(ptr, get_array_size(nmemb, size));
}

#define MallocNew(T) ((T *) Malloc(sizeof(T)))
#define MallocArray(T, n) ((T *) Malloc2(n, sizeof(T)))
#define ReallocArray(T, n, x) ((T *) Realloc2((void *)(x), n, sizeof(T)))
#define Free(x) free(x)

// array.c

struct ARR_Instance_Record {
void *data;
unsigned int elem_size;
unsigned int used;
unsigned int allocated;
};

typedef struct ARR_Instance_Record *ARR_Instance;

ARR_Instance
ARR_CreateInstance(unsigned int elem_size)
{
ARR_Instance array;

assert(elem_size > 0);

array = MallocNew(struct ARR_Instance_Record);

array->data = NULL;
array->elem_size = elem_size;
array->used = 0;
array->allocated = 0;

return array;
}

void *
ARR_GetElement(ARR_Instance array, unsigned int index)
{
assert(index < array->used); // UNKNOWN
return (void *)((char *)array->data + (size_t)index * array->elem_size);
}

static void
realloc_array(ARR_Instance array, unsigned int min_size)
{
assert(min_size <= 2 * min_size); // UNKNOWN
if (array->allocated >= min_size && array->allocated <= 2 * min_size)
return;

if (array->allocated < min_size) {
while (array->allocated < min_size)
array->allocated = array->allocated ? 2 * array->allocated : 1;
} else {
array->allocated = min_size;
}

array->data = Realloc2(array->data, array->allocated, array->elem_size);
}

void *
ARR_GetNewElement(ARR_Instance array)
{
array->used++;
realloc_array(array, array->used);
return ARR_GetElement(array, array->used - 1);
}

unsigned int
ARR_GetSize(ARR_Instance array)
{
return array->used;
}

// sched.c

typedef void* SCH_ArbitraryArgument;
typedef void (*SCH_FileHandler)(SCH_ArbitraryArgument);

typedef struct {
SCH_FileHandler handler;
SCH_ArbitraryArgument arg;
} FileHandlerEntry;

static ARR_Instance file_handlers;

void
SCH_Initialise(void)
{
file_handlers = ARR_CreateInstance(sizeof (FileHandlerEntry));
}

void
SCH_AddFileHandler
(SCH_FileHandler handler, SCH_ArbitraryArgument arg)
{
int fd; // rand
FileHandlerEntry *ptr;

while (ARR_GetSize(file_handlers) <= fd) {
ptr = ARR_GetNewElement(file_handlers);
ptr->handler = NULL;
ptr->arg = NULL;
}

ptr = ARR_GetElement(file_handlers, fd);

/* Don't want to allow the same fd to register a handler more than
once without deleting a previous association - this suggests
a bug somewhere else in the program. */
assert(!ptr->handler); // UNKNOWN

ptr->handler = handler;
ptr->arg = arg;
}

static void
dispatch_filehandlers()
{
FileHandlerEntry *ptr;
int fd; // rand

ptr = (FileHandlerEntry *)ARR_GetElement(file_handlers, fd);
SCH_FileHandler stuff = *(ptr->handler);
if (ptr->handler)
(ptr->handler)(ptr->arg);
}

// nameserv_async.c

typedef void (*DNS_NameResolveHandler)(void *anything);

struct DNS_Async_Instance {
DNS_NameResolveHandler handler;
void *arg;
pthread_t thread;
};

static void *
start_resolving(void *anything)
{
struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything;

return NULL;
}

static void
end_resolving(void *anything)
{
struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything;

DNS_NameResolveHandler h = inst->handler;
(inst->handler)(inst->arg);

Free(inst);
}

void
DNS_Name2IPAddressAsync(DNS_NameResolveHandler handler, void *anything)
{
struct DNS_Async_Instance *inst;

inst = MallocNew(struct DNS_Async_Instance);
inst->handler = handler;
inst->arg = anything;

pthread_create(&inst->thread, NULL, start_resolving, inst);

SCH_AddFileHandler(end_resolving, inst);
}

// nameserv_async.c copy

typedef void (*DNS_NameResolveHandler2)(void *anything2);

struct DNS_Async_Instance2 {
DNS_NameResolveHandler2 handler2;
void *arg2;
pthread_t thread2;
};

static void *
start_resolving2(void *anything2)
{
struct DNS_Async_Instance2 *inst2 = (struct DNS_Async_Instance2 *)anything2;

return NULL;
}

static void
end_resolving2(void *anything2)
{
struct DNS_Async_Instance2 *inst2 = (struct DNS_Async_Instance2 *)anything2;

DNS_NameResolveHandler2 h = inst2->handler2;
(inst2->handler2)(inst2->arg2);

Free(inst2);
}

void
DNS_Name2IPAddressAsync2(DNS_NameResolveHandler2 handler2, void *anything2)
{
struct DNS_Async_Instance2 *inst2;

inst2 = MallocNew(struct DNS_Async_Instance2);
inst2->handler2 = handler2;
inst2->arg2 = anything2;

pthread_create(&inst2->thread2, NULL, start_resolving2, inst2);

SCH_AddFileHandler(end_resolving2, inst2);
}

// stub

void foo(void *arg) {
assert(1); // reachable
}

void bar(void *arg) {
int *p = arg;
int y = *p;
assert(1); // reachable
assert(y); // TODO
}

int main() {
SCH_Initialise();
DNS_Name2IPAddressAsync(foo, NULL);
int x = 1;
DNS_Name2IPAddressAsync2(bar, &x);
dispatch_filehandlers();
return 0;
}

0 comments on commit 0161b64

Please sign in to comment.