-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add test for sets struct domain for #716.
- Loading branch information
Showing
2 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
276 changes: 276 additions & 0 deletions
276
tests/regression/43-struct-domain/29-chrony-nameserv-sched-array2-set-struct.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
File renamed without changes.