Fixes for queue and stack

This patch does misc fixes in queue and stack:
* the *_new() were not handling OOM correctly ;
* the *_Contains() methods were not using the equals cb;
* the lock were not always taken when accessing internal members;
This commit is contained in:
Hardening 2014-04-18 16:27:51 +02:00
parent 4da5cc9f9a
commit 6febe88026
3 changed files with 107 additions and 22 deletions

View File

@ -39,7 +39,7 @@ typedef void* (*OBJECT_NEW_FN)(void);
typedef void (*OBJECT_INIT_FN)(void* obj);
typedef void (*OBJECT_UNINIT_FN)(void* obj);
typedef void (*OBJECT_FREE_FN)(void* obj);
typedef void (*OBJECT_EQUALS_FN)(void* objA, void* objB);
typedef BOOL (*OBJECT_EQUALS_FN)(void* objA, void* objB);
struct _wObject
{
@ -83,7 +83,7 @@ WINPR_API void Queue_Clear(wQueue* queue);
WINPR_API BOOL Queue_Contains(wQueue* queue, void* obj);
WINPR_API void Queue_Enqueue(wQueue* queue, void* obj);
WINPR_API BOOL Queue_Enqueue(wQueue* queue, void* obj);
WINPR_API void* Queue_Dequeue(wQueue* queue);
WINPR_API void* Queue_Peek(wQueue* queue);

View File

@ -40,7 +40,15 @@
int Queue_Count(wQueue* queue)
{
return queue->size;
int ret;
if (queue->synchronized)
EnterCriticalSection(&queue->lock);
ret = queue->size;
if (queue->synchronized)
LeaveCriticalSection(&queue->lock);
return ret;
}
/**
@ -114,7 +122,7 @@ BOOL Queue_Contains(wQueue* queue, void* obj)
for (index = 0; index < queue->tail; index++)
{
if (queue->array[index] == obj)
if (queue->object.fnObjectEquals(queue->array[index], obj))
{
found = TRUE;
break;
@ -131,8 +139,10 @@ BOOL Queue_Contains(wQueue* queue, void* obj)
* Adds an object to the end of the Queue.
*/
void Queue_Enqueue(wQueue* queue, void* obj)
BOOL Queue_Enqueue(wQueue* queue, void* obj)
{
BOOL ret = TRUE;
if (queue->synchronized)
EnterCriticalSection(&queue->lock);
@ -140,12 +150,20 @@ void Queue_Enqueue(wQueue* queue, void* obj)
{
int old_capacity;
int new_capacity;
void **newArray;
old_capacity = queue->capacity;
new_capacity = queue->capacity * queue->growthFactor;
newArray = (void **)realloc(queue->array, sizeof(void*) * new_capacity);
if (!newArray)
{
ret = FALSE;
goto out;
}
queue->capacity = new_capacity;
queue->array = (void**) realloc(queue->array, sizeof(void*) * queue->capacity);
queue->array = newArray;
ZeroMemory(&(queue->array[old_capacity]), old_capacity * sizeof(void*));
if (queue->tail < old_capacity)
@ -161,8 +179,10 @@ void Queue_Enqueue(wQueue* queue, void* obj)
SetEvent(queue->event);
out:
if (queue->synchronized)
LeaveCriticalSection(&queue->lock);
return ret;
}
/**
@ -213,6 +233,11 @@ void* Queue_Peek(wQueue* queue)
return obj;
}
static BOOL default_queue_equals(void *obj1, void *obj2)
{
return (obj1 == obj2);
}
/**
* Construction, Destruction
*/
@ -240,13 +265,18 @@ wQueue* Queue_New(BOOL synchronized, int capacity, int growthFactor)
if (!queue->array)
goto out_free;
InitializeCriticalSectionAndSpinCount(&queue->lock, 4000);
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!queue->event)
goto out_free_array;
if (!InitializeCriticalSectionAndSpinCount(&queue->lock, 4000))
goto out_free_event;
queue->object.fnObjectEquals = default_queue_equals;
return queue;
out_free_event:
CloseHandle(queue->event);
out_free_array:
free(queue->array);
out_free:
@ -256,6 +286,9 @@ out_free:
void Queue_Free(wQueue* queue)
{
if (!queue)
return;
Queue_Clear(queue);
CloseHandle(queue->event);

View File

@ -38,12 +38,17 @@
int Stack_Count(wStack* stack)
{
int ret;
if (stack->synchronized)
{
EnterCriticalSection(&stack->lock);
}
ret = stack->size;
return 0;
if (stack->synchronized)
LeaveCriticalSection(&stack->lock);
return ret;
}
/**
@ -65,7 +70,23 @@ BOOL Stack_IsSynchronized(wStack* stack)
void Stack_Clear(wStack* stack)
{
int index;
if (stack->synchronized)
EnterCriticalSection(&stack->lock);
for (index = 0; index < stack->size; index++)
{
if (stack->object.fnObjectFree)
stack->object.fnObjectFree(stack->array[index]);
stack->array[index] = NULL;
}
stack->size = 0;
if (stack->synchronized)
LeaveCriticalSection(&stack->lock);
}
/**
@ -74,7 +95,25 @@ void Stack_Clear(wStack* stack)
BOOL Stack_Contains(wStack* stack, void* obj)
{
return FALSE;
int i;
BOOL found = FALSE;
if (stack->synchronized)
EnterCriticalSection(&stack->lock);
for (i = 0; i < stack->size; i++)
{
if (stack->object.fnObjectEquals(stack->array[i], obj))
{
found = TRUE;
break;
}
}
if (stack->synchronized)
LeaveCriticalSection(&stack->lock);
return found;
}
/**
@ -138,6 +177,12 @@ void* Stack_Peek(wStack* stack)
return obj;
}
static BOOL default_stack_equals(void *obj1, void *obj2)
{
return (obj1 == obj2);
}
/**
* Construction, Destruction
*/
@ -146,26 +191,33 @@ wStack* Stack_New(BOOL synchronized)
{
wStack* stack = NULL;
stack = (wStack*) malloc(sizeof(wStack));
stack = (wStack *)calloc(1, sizeof(wStack));
if (!stack)
return NULL;
if (stack)
{
stack->synchronized = synchronized;
stack->object.fnObjectEquals = default_stack_equals;
stack->synchronized = synchronized;
if (stack->synchronized)
InitializeCriticalSectionAndSpinCount(&stack->lock, 4000);
stack->capacity = 32;
stack->array = (void**) malloc(sizeof(void*) * stack->capacity);
if (!stack->array)
goto out_free;
stack->size = 0;
stack->capacity = 32;
stack->array = (void**) malloc(sizeof(void*) * stack->capacity);
}
if (stack->synchronized && !InitializeCriticalSectionAndSpinCount(&stack->lock, 4000))
goto out_free_array;
return stack;
out_free_array:
free(stack->array);
out_free:
free(stack);
return NULL;
}
void Stack_Free(wStack* stack)
{
if (stack)
if (!stack)
{
if (stack->synchronized)
DeleteCriticalSection(&stack->lock);