Removed memory leaks, minor bug and security fixes

This commit is contained in:
XOR 2023-04-05 00:00:46 +02:00
parent 6449cb0374
commit 289de54e7e

76
main.c
View file

@ -4,6 +4,7 @@
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <assert.h>
#define WORD 32
#define TRANSFORM_TABLE_MAX_RAND 4294967296
@ -44,6 +45,8 @@ typedef struct
// Returns -1 when the hashtable is full
int get_empty_hashtable_slot(shash_hashtable_t *hashtable)
{
assert(hashtable != NULL);
for (int i = 0; i < hashtable->table_size; i++)
{
if (hashtable->hash_table[i].key == 0)
@ -53,12 +56,17 @@ int get_empty_hashtable_slot(shash_hashtable_t *hashtable)
return -1;
}
void shash_init_hashtable(shash_hashtable_t *hashtable, unsigned int table_size)
int shash_init_hashtable(shash_hashtable_t *hashtable, unsigned int table_size)
{
// Initialize the RNG to a non-constant value, to make the output less pseudo random
srand(time(NULL));
// Create a random transformation table
srand(0);
// srand(time(NULL));
unsigned int *table = malloc((CHAR_MAX - CHAR_MIN) * sizeof(int));
if(table == NULL)
{
return EXIT_FAILURE;
}
for (int i = 0; i < CHAR_MAX - CHAR_MIN; i++)
{
@ -67,13 +75,20 @@ void shash_init_hashtable(shash_hashtable_t *hashtable, unsigned int table_size)
hashtable->transformation_table = table;
hashtable->hash_table = malloc(table_size * sizeof(shash_table_element_t));
if(hashtable->hash_table == NULL)
{
return EXIT_FAILURE;
}
memset(hashtable->hash_table, 0, table_size * sizeof(shash_table_element_t));
hashtable->table_size = table_size;
return EXIT_SUCCESS;
}
unsigned int shash_hash(char *key, unsigned int len, shash_hashtable_t *hashtable)
{
assert(hashtable != NULL);
if (SIMULATE_COLLISIONS == 1)
{
return SIMULATED_COLLISION_HASH;
@ -91,37 +106,48 @@ unsigned int shash_hash(char *key, unsigned int len, shash_hashtable_t *hashtabl
int shash_set(char *key, unsigned int len, void *data, shash_hashtable_t *hashtable)
{
assert(key != NULL);
assert(data != NULL);
assert(hashtable != NULL);
unsigned int slot = shash_hash(key, len, hashtable);
//Loop to the end of the linked list
while(hashtable->hash_table[slot].encountered_collision != 0){
slot = hashtable->hash_table[slot].next_key_location;
// Loop to the end of the linked list
while (hashtable->hash_table[slot].encountered_collision != 0 && strcmp(hashtable->hash_table[slot].key, key) != 0)
{
slot = hashtable->hash_table[slot].next_key_location;
}
shash_table_element_t table_element = {
.key = key,
.data = data};
shash_table_element_t table_element =
{
.key = strndup(key, len),
.data = data};
if (hashtable->hash_table[slot].key == 0)
{
hashtable->hash_table[slot] = table_element;
return 0;
}
else
{
int empty_slot = get_empty_hashtable_slot(hashtable);
if (empty_slot != -1)
{
hashtable->hash_table[slot].encountered_collision = 1;
hashtable->hash_table[slot].encountered_collision = 1;
hashtable->hash_table[slot].next_key_location = empty_slot;
hashtable->hash_table[empty_slot] = table_element;
return 0;
}
}
//hashtable full
// hashtable full
return -1;
}
void *shash_get(char *key, unsigned int len, shash_hashtable_t *hashtable)
{
assert(key != NULL);
assert(hashtable != NULL);
unsigned int slot = shash_hash(key, len, hashtable);
while (strcmp(hashtable->hash_table[slot].key, key) != 0)
@ -141,6 +167,21 @@ void *shash_get(char *key, unsigned int len, shash_hashtable_t *hashtable)
return hashtable->hash_table[slot].data;
}
void shash_destroy_hashtable(shash_hashtable_t *hashtable)
{
assert(hashtable != 0);
for(int i = 0; i < hashtable->table_size; i++)
{
if(hashtable->hash_table[i].key != NULL)
{
free(hashtable->hash_table[i].key);
}
}
free(hashtable->transformation_table);
free(hashtable->hash_table);
}
int main(void)
{
// Initialize an empty hashtable
@ -148,11 +189,16 @@ int main(void)
shash_init_hashtable(&hashtable, 100);
// Store some data
shash_set("FOO", 3, "Hello, World", &hashtable);
shash_set("FOO", 3, "Hello", &hashtable);
shash_set("BAR", 3, "World!", &hashtable);
// And retrieve it
char *retrieved_val = shash_get("FOO", 3, &hashtable);
printf("Stored string %s\n", retrieved_val);
char *retrieved_foo = shash_get("FOO", 3, &hashtable);
char *retrieved_bar = shash_get("BAR", 3, &hashtable);
printf("%s, %s\n", retrieved_foo, retrieved_bar);
// Destroy the hashtable
shash_destroy_hashtable(&hashtable);
return 0;
}