From b3bd3df103a5a75d267b2b79e85558768b1dc4bb Mon Sep 17 00:00:00 2001 From: "@syxhe" Date: Sun, 23 Mar 2025 22:11:15 -0500 Subject: Fix a whole bunch of shit, create an arena implementation --- src/Makefile | 6 +- src/arena.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/arena.h | 23 +++++++ src/encryption.c | 40 +++++------- src/encryption.h | 7 ++- src/ll.c | 2 + src/shared.c | 115 +++++++--------------------------- src/shared.h | 13 +++- 8 files changed, 264 insertions(+), 125 deletions(-) create mode 100644 src/arena.c create mode 100644 src/arena.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index bcb4670..4a0d316 100644 --- a/src/Makefile +++ b/src/Makefile @@ -22,10 +22,12 @@ all: main main: main.o shared.o -main.o: main.c shared.h +ll.o: ll.c ll.h +main.o: main.c +arena.o: arena.c arena.h shared.o: shared.c shared.h encryption: encryption.c encryption.h shared.o shared.h c clean: - rm -rvf $(BINARIES) $(wildcard *.o) $(wildcard *.test*) \ No newline at end of file + rm -rvf $(BINARIES) $(wildcard *.o) $(wildcard *.test*) $(wildcard *.enc) \ No newline at end of file diff --git a/src/arena.c b/src/arena.c new file mode 100644 index 0000000..d340f3a --- /dev/null +++ b/src/arena.c @@ -0,0 +1,183 @@ +#include "arena.h" +#include "shared.h" + +#include +#include +#include +#include +#include + +typedef struct an { + void *membase; + void *memcur; + size_t allocated; + size_t used; + + struct an *next; +} arenanode; + +typedef struct arena { + arenanode *start; + arenanode *current; + + // For keeping track of the largest possible thing that can be allocated to one node + size_t node_memspace; +} arena; + +int arenanode_init(arenanode **an, size_t bytes) { + (*an) = xcalloc(1, sizeof(**an)); + if(!(*an)) + return -1; + + (*an)->allocated = bytes; + (*an)->used = 0; + (*an)->next = NULL; + + void *mem = xcalloc(bytes, 1); + if(!mem) { + free((*an)); + (*an) = NULL; + return -1; + } + + (*an)->membase = mem; + (*an)->memcur = mem; + + return 0; +} + +int arena_init(arena **a, size_t bytes) { + if(!ISPOWOF2(MEM_ALIGN_BYTES)) + XALLOC_EXIT(" \"MEM_ALIGN_BYTES\" is not a power of 2. Refusing to create a new arena"); + + (*a) = xcalloc(1, sizeof(**a)); + if(!(*a)) + return -1; + (*a)->start = NULL; + (*a)->current = NULL; + (*a)->node_memspace = bytes; + + arenanode *base; + if(arenanode_init(&base, bytes) < 0) { + free(*a); + (*a) = NULL; + return -1; + } + + (*a)->start = base; + (*a)->current = base; + + return 0; +} + +void* arena_alloc(arena * const arena, size_t bytes) { + if(!arena) { + errno = EINVAL; + return NULL; + } + if(bytes > arena->node_memspace) { + errno = ENOMEM; + return NULL; + } + if(!ISPOWOF2(MEM_ALIGN_BYTES)) + XALLOC_EXIT(" \"MEM_ALIGN_BYTES\" is not a power of 2. Refusing to allocate any memory"); + + if(bytes > ((arena->current)->allocated - (arena->current)->used)) { + arenanode *new; + if(arenanode_init(&new, arena->node_memspace) < 0) + return NULL; + + arena->current->next = new; + arena->current = new; + } + + size_t alignment = MEM_ALIGN(bytes); + size_t offset = bytes + alignment; + + void *mem = arena->current->memcur; + arena->current->memcur = (void*)(((uint8_t*)arena->current->memcur) + offset); + + arena->current->used += offset; + + return mem; + + // Note: This implementation assumes that malloc provides already-aligned memory. If it + // doesn't, that sucks and blows everything up +} + +int arena_free(arena **arena) { + if(!arena) { + errno = EINVAL; + return -1; + } + if(!(*arena)) { + errno = EINVAL; + return -1; + } + + (*arena)->current = (*arena)->start; + for(arenanode *n; (*arena)->current != NULL;) { + n = (*arena)->current->next; + + free((*arena)->current->membase); + free((*arena)->current); + + (*arena)->current = n; + } + free((*arena)); + (*arena) = NULL; + + return 0; +} + +int arena_clear(arena **arena) { + if(!arena) { + errno = EINVAL; + return -1; + } + if(!(*arena)) { + errno = EINVAL; + return -1; + } + + size_t bytes = (*arena)->node_memspace; + + int ret = 0; + if((ret = arena_free(arena)) < 0) + return ret; + return arena_init(arena, bytes); +} + + + +// Simple Arena is an arena that can't expand whenever allocating memory, meaning what you originally allocated is what you get + +typedef arena simplearena; + +int simplearena_init(simplearena **a, size_t bytes) { + return arena_init(a, bytes); +} + +void* simplearena_alloc(simplearena * const a, size_t bytes) { + // The criteria to allocate new memory in arena_alloc is 'bytes > ((a->current)->allocated - (a->current)->used)', so if this + // is true, just return NULL & set errno + + if(!a) { + errno = EINVAL; + return NULL; + } + if(bytes > ((a->current)->allocated - (a->current)->used)) { + errno = ENOMEM; + return NULL; + } + + return arena_alloc(a, bytes); +} + +int simplearena_free(simplearena **a) { + return arena_free(a); +} + +int simplearena_clear(simplearena **a) { + return arena_clear(a); +} \ No newline at end of file diff --git a/src/arena.h b/src/arena.h new file mode 100644 index 0000000..23dc664 --- /dev/null +++ b/src/arena.h @@ -0,0 +1,23 @@ +#ifndef __VXGG_REWRITE___ARENA_H___25077218513438___ +#define __VXGG_REWRITE___ARENA_H___25077218513438___ + +#include + +typedef struct arena arena; +typedef arena simplearena; + +#define ISPOWOF2(x) (((x) & ((x) - 1)) == 0) +const size_t MEM_ALIGN_BYTES = (2 * sizeof(void*)); +#define MEM_ALIGN(x) ((x) + (((x) & (MEM_ALIGN_BYTES - 1)) != 0) * (MEM_ALIGN_BYTES - ((x) & (MEM_ALIGN_BYTES - 1)))) + +int arena_init(arena **a, size_t bytes); +void* arena_alloc(arena * const arena, size_t bytes); +int arena_free(arena **arena); +int arena_clear(arena **arena); + +int simplearena_init(simplearena **a, size_t bytes); +void* simplearena_alloc(simplearena * const a, size_t bytes); +int simplearena_free(simplearena **a); +int simplearena_free(simplearena **a); + +#endif \ No newline at end of file diff --git a/src/encryption.c b/src/encryption.c index 8b0ac83..9b8715e 100644 --- a/src/encryption.c +++ b/src/encryption.c @@ -19,11 +19,9 @@ #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 void naclfaildefault(void *none) { none = none; // Makes gcc happy - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + if(___VXGG___VERBOSE_ERRORS___) error(1, ENOTSUP, "Couldn't initialize sodium for some reason. Quitting..."); - #else - exit(EXIT_FAILURE); - #endif + exit(EXIT_FAILURE); } int checksodiumcb(const vxgg_naclfailcb callback, void *data) { @@ -49,15 +47,14 @@ void vxgg_setsodiumfailcb(vxgg_naclfailcb cb, void *data) { #endif void checksodium(void) { - #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 - checksodiumcb(NULL, NULL); + #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 + checksodiumcb(NULL, NULL); #else - if(sodium_init() < 0) - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, ENOTSUP, "Couldn't initialize sodium for some reason. Quitting..."); - #else - exit(EXIT_FAILURE); - #endif + if(sodium_init() < 0) { + if(___VXGG___VERBOSE_ERRORS___) + error(1, ENOTSUP, "Couldn't initialize sodium for some reason. Quitting..."); + exit(EXIT_FAILURE); + } #endif return; @@ -84,7 +81,7 @@ int maketmp(const char * const dest) { } int encrypttotmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { - #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 + #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 checksodium(); #endif @@ -176,7 +173,7 @@ int genpassword(char **str, unsigned int words) { // Early returns if(words < 1) return 0; - #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 + #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 checksodium(); #endif @@ -203,22 +200,13 @@ int genpassword(char **str, unsigned int words) { // sodium_malloc wrapper. Calls `error()` or `abort()` depnding on the value of `___VXGG___XALLOC_EXIT_ON_ERROR___`. Will make sure libsodium is initialized if `___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0` void* xsodium_malloc(size_t size) { - #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 + #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 checksodium(); #endif void *mem = sodium_malloc(size); - if(mem == NULL) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " could not allocate memory... Quitting"); - #else - exit(EXIT_FAILURE); - #endif - #endif - - abort(); - } + if(mem == NULL) + XALLOC_EXIT(" could not allocate memory... Quitting"); return mem; } diff --git a/src/encryption.h b/src/encryption.h index 1c38141..418e7f6 100644 --- a/src/encryption.h +++ b/src/encryption.h @@ -8,7 +8,8 @@ #define CHUNK_SIZE ((int)(1 << 12)) -#if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 +// TODO: What the fuck was I thinking when I did any of this callback shit? Make this a different macro and decouple it from ALWAYS_CHECK +#if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 // Definition for the callback function that fires when a call to checksodium fails typedef void (*vxgg_naclfailcb)(void*); @@ -18,7 +19,7 @@ void vxgg_setsodiumfailcb(const vxgg_naclfailcb cb, void *data); #endif -// I need to store a dictionary of valid words for generating a password, and I don't want to read it in from another file, so I'm experimenting with this +// Fuck reading from a file. Even if someone ran strings on the binary and got this they wouldn't be able to regenerate the key #define PASSWORD_WORDS (\ (const char *[]){\ "the", "of", "to", "and", "for", "our", "their", "has", "in", "he", "a", "them", "that", "these", "by", "have", "we", "us",\ @@ -73,7 +74,7 @@ void vxgg_setsodiumfailcb(const vxgg_naclfailcb cb, void *data); "reliance", "divine", "providence", "mutually", "pledge", "each", "fortunes", "sacred", "honor"\ }\ ) -#define PASSWORD_WORDS_LEN (STATICARR_SIZE(PASSWORD_WORDS)) +#define PASSWORD_WORDS_LEN (STATIC_ARRAY_LEN(PASSWORD_WORDS)) // Checks if sodium is initialized. Initializes it if not. If `___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0`, it's possible to set an error callback to avoid exiting the entire program. Otherwise calls `error()` if libsodium can't initialize void checksodium(void); diff --git a/src/ll.c b/src/ll.c index c94a45b..b42f631 100644 --- a/src/ll.c +++ b/src/ll.c @@ -1,6 +1,8 @@ #include "ll.h" +#include "shared.h" #include +#include void dlinkedlist_init(dlinkedlist **ll) { (*ll) = xcalloc(1, sizeof(**ll)); diff --git a/src/shared.c b/src/shared.c index d67e362..72ede56 100644 --- a/src/shared.c +++ b/src/shared.c @@ -1,45 +1,23 @@ #include "shared.h" -#include #include #include #include #include #include -#include void* xcalloc(size_t nmemb, size_t size) { void *mem = calloc(nmemb, size); - - if(!mem) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " Could not allocate memory"); - #else - exit(EXIT_FAILURE); - #endif - #endif - - abort(); - } + if(!mem) + XALLOC_EXIT(" Could not allocate memory"); - return mem; } void* xreallocarray(void *ptr, size_t nmemb, size_t size) { void *mem = reallocarray(ptr, nmemb, size); - if(mem == NULL) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " Could not allocate memory"); - #else - exit(EXIT_FAILURE); - #endif - #endif - - abort(); - } + if(mem == NULL) + XALLOC_EXIT(" Could not allocate memory"); return mem; } @@ -63,9 +41,9 @@ int readwholebuffer(char **str, unsigned long int initsize, int fd) { tmp = realloc(lstr, csize * sizeof(char)); if(!tmp) { - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + if(___VXGG___VERBOSE_ERRORS___) error(0, errno, "Could not reallocate enough space for lstr"); - #endif + free(lstr); lstr = NULL; // Need to set this because of the break bytesread = -100; @@ -75,9 +53,9 @@ int readwholebuffer(char **str, unsigned long int initsize, int fd) { } } if(bytesread < 0 && bytesread != -100) { - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + if(___VXGG___VERBOSE_ERRORS___) error(0, errno, "Ran into a read() error"); - #endif + free(lstr); lstr = NULL; } @@ -85,9 +63,9 @@ int readwholebuffer(char **str, unsigned long int initsize, int fd) { if(lstr) { tmp = realloc(lstr, csize - ccap + 1); if(!tmp) { - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 + if(___VXGG___VERBOSE_ERRORS___) error(0, errno, "Could not shrink lstr after reading buffer"); - #endif + free(lstr); bytesread = -100; } @@ -127,16 +105,8 @@ char *xdirname(const char * const path) { char *tmp = NULL; if(!path) { // Path being null is a special case which should return super early, before anything else tmp = strdup("."); - if(!tmp) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " could not strdup \".\" for set path result \"NULL\""); - #else - exit(EXIT_FAILURE); - #endif - #endif - abort(); - } + if(!tmp) + XALLOC_EXIT(" could not strdup \".\" for set path result \"NULL\""); return tmp; } @@ -147,16 +117,9 @@ char *xdirname(const char * const path) { if(strcmp(path, "..") == 0 && !flag) {tmp = strdup("."); flag++;} if(flag) { - if(!tmp) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " could not strdup a set path result"); - #else - exit(EXIT_FAILURE); - #endif - #endif - abort(); - } + if(!tmp) + XALLOC_EXIT(" could not strdup a set path result"); + return tmp; } @@ -173,16 +136,8 @@ char *xdirname(const char * const path) { // Get a temp copy of the path for manipulation purposes tmp = strdup(path); - if(!tmp) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " could not strdup the given path \"%s\" for internal manipulation", path); - #else - exit(EXIT_FAILURE); - #endif - #endif - abort(); - } + if(!tmp) + XALLOC_EXIT(" could not strdup the given path \"%s\" for internal manipulation", , path); // If there's a trailing '/', delete it size_t pathlen = strlen(path); @@ -204,31 +159,15 @@ char *xdirname(const char * const path) { if(count == 0) { free(tmp); tmp = strdup("."); - if(!tmp) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " could not strdup \".\" for set path result"); - #else - exit(EXIT_FAILURE); - #endif - #endif - abort(); - } + if(!tmp) + XALLOC_EXIT(" could not strdup \".\" for set path result"); return tmp; } if(count == 1) { free(tmp); tmp = strdup("/"); - if(!tmp) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " could not strdup \"/\" for set path result"); - #else - exit(EXIT_FAILURE); - #endif - #endif - abort(); - } + if(!tmp) + XALLOC_EXIT(" could not strdup \"/\" for set path result"); return tmp; } @@ -241,16 +180,8 @@ char *xdirname(const char * const path) { } char * const actual = strdup(tmp); - if(!actual) { - #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 - #if defined ___VXGG___VERBOSE_ERRORS___ && ___VXGG___VERBOSE_ERRORS___ > 0 - error(1, errno, " could not strdup tmp string to make a shorter end string"); - #else - exit(EXIT_FAILURE); - #endif - #endif - abort(); - } + if(!actual) + XALLOC_EXIT(" could not strdup tmp string to make a shorter end string"); free(tmp); return actual; diff --git a/src/shared.h b/src/shared.h index 3c23676..ee3e06b 100644 --- a/src/shared.h +++ b/src/shared.h @@ -2,9 +2,8 @@ #define __VXGG_REWRITE___SHARED_H___3880294315821___ #include -#include -#define STATICARR_SIZE(arr) (sizeof((arr))/sizeof((arr)[0])) +#define STATIC_ARRAY_LEN(arr) (sizeof((arr))/sizeof((arr)[0])) // Defines how `x___alloc()` functions should exit. `___VXGG___XALLOC_EXIT_ON_ERROR___ > 0` calls `error()`, and thus functions // registered with `atexit()` and `on_exit()`. `___VXGG___XALLOC_EXIT_ON_ERROR___ <= 0` calls `abort()` on error. `x___alloc()` @@ -15,6 +14,16 @@ // `___VXGG___VERBOSE_ERRORS___ > 0` will print diagnostic error messages, and will do nothing otherwise #define ___VXGG___VERBOSE_ERRORS___ 1 +// Macro to exit on an alloc error instead of doing the terrible nested if statement that was being used previously +#define XALLOC_EXIT(msg, ...) do {\ + if(!___VXGG___XALLOC_EXIT_ON_ERROR___)\ + abort();\ + if(!___VXGG___VERBOSE_ERRORS___)\ + exit(EXIT_FAILURE);\ + error(EXIT_FAILURE, errno, (msg)__VA_ARGS__);\ + exit(EXIT_FAILURE); /* Makes gcc happy */\ +} while (0) + // `calloc()` with error checking. Calls `error()` or `abort()` on error, depending on the value of `___VXGG___XALLOC_EXIT_ON_ERROR___` void* xcalloc(size_t nmemb, size_t size); -- cgit v1.2.3