diff options
author | Ratakor <ratakor@disroot.org> | 2023-08-08 05:01:39 +0200 |
---|---|---|
committer | Ratakor <ratakor@disroot.org> | 2023-08-08 05:01:39 +0200 |
commit | b8d2bba45e9bf21714bf65731397faa1e4189866 (patch) | |
tree | b94a6e96940354f6c0ea005e9c74bbcd914a6a75 | |
parent | f43349d5830fdaa9cd76781d482bca1e18be3021 (diff) |
Remove libre, add dalloc, add ubik func to util
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | src/Makefile | 4 | ||||
-rw-r--r-- | src/dalloc.c | 420 | ||||
-rw-r--r-- | src/dalloc.h | 70 | ||||
-rw-r--r-- | src/main.c | 5 | ||||
-rw-r--r-- | src/nolan.h | 17 | ||||
-rw-r--r-- | src/stats.c | 5 | ||||
-rw-r--r-- | src/util.c | 125 |
8 files changed, 637 insertions, 10 deletions
@@ -5,7 +5,6 @@ A discord bot for Orna. - [concord](https://github.com/Cogmasters/concord) - [tesseract](https://github.com/tesseract-ocr/tesseract) - [gd](https://github.com/libgd/libgd) -- [libre](https://github.com/ratakor/libre) ## TODO diff --git a/src/Makefile b/src/Makefile index f0a0a42..d165209 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,6 +11,7 @@ OBJS = cmd_correct.o \ cmd_source.o \ cmd_time.o \ cmd_uraid.o \ + dalloc.o \ init.o \ main.o \ ocr.o \ @@ -20,7 +21,6 @@ OBJS = cmd_correct.o \ stats.o \ util.o -RELIBS = -lre DISCORDLIBS = -ldiscord -lcurl -lpthread TESSLIBS = -ltesseract -lleptonica GDLIBS = -lgd -lpng -lz -ljpeg -lfreetype -lm @@ -28,7 +28,7 @@ GDLIBS = -lgd -lpng -lz -ljpeg -lfreetype -lm WFLAGS = -pedantic -Werror -Wall -Wextra -Waggregate-return -Wshadow\ -Wmissing-prototypes -Wunused-macros -Wdouble-promotion CFLAGS += -std=c99 -D_DEFAULT_SOURCE ${WFLAGS} -LDFLAGS += ${RELIBS} ${DISCORDLIBS} ${TESSLIBS} ${GDLIBS} +LDFLAGS += ${DISCORDLIBS} ${TESSLIBS} ${GDLIBS} all: ${BIN} diff --git a/src/dalloc.c b/src/dalloc.c new file mode 100644 index 0000000..9e28c50 --- /dev/null +++ b/src/dalloc.c @@ -0,0 +1,420 @@ +/* + * Copyright © 2023, Ratakor <ratakor@disroot.org> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <errno.h> +#include <pthread.h> + +#define DALLOC_INTERNAL +#include "dalloc.h" + +#define EXIT_STATUS EXIT_FAILURE +#define OVER_ALLOC 64 +#define MAGIC_NUMBER 0xdead + +#define x1 ((char)(MAGIC_NUMBER)) +#define x2 x1, x1 +#define x4 x2, x2 +#define x8 x4, x4 +#define x16 x8, x8 +#define x32 x16, x16 +#define x64 x32, x32 +#define xCAT(X) x##X +#define MAGIC_INIT(X) xCAT(X) +#define OVERFLOW(p, s) (memcmp(((char *)(p)) + (s), magic_numbers, OVER_ALLOC)) + +typedef struct dalloc_ptr dalloc_ptr; +struct dalloc_ptr { + void *p; + size_t siz; + char *comment; + char *file; + int ignored; + int line; + dalloc_ptr *next; +}; + +static void eprintf(const char *fmt, ...); +static char *xstrdup(const char *s, char *file, int line); +static dalloc_ptr *find_ptr(void *p, char *file, int line); +static void check_overflow(dalloc_ptr *dp, char *file, int line); + +static const char magic_numbers[OVER_ALLOC] = { MAGIC_INIT(OVER_ALLOC) }; +static pthread_mutex_t dalloc_mutex = PTHREAD_MUTEX_INITIALIZER; +static dalloc_ptr *head; + +static void +eprintf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static char * +xstrdup(const char *s, char *file, int line) +{ + char *p; + size_t siz; + + siz = strlen(s) + 1; + if ((p = malloc(siz)) == NULL) { + eprintf("%s:%d: dalloc: %s", file, line, strerror(errno)); + pthread_mutex_unlock(&dalloc_mutex); + exit(EXIT_STATUS); + } + + return memcpy(p, s, siz); +} + +static dalloc_ptr * +find_ptr(void *p, char *file, int line) +{ + dalloc_ptr *dp; + + for (dp = head; dp && dp->p != p; dp = dp->next); + + if (dp == NULL) { + eprintf("%s:%d: dalloc: Unknown pointer %p\n", file, line, p); + pthread_mutex_unlock(&dalloc_mutex); + exit(EXIT_STATUS); + } + + return dp; +} + +static void +check_overflow(dalloc_ptr *dp, char *file, int line) +{ + if (!OVERFLOW(dp->p, dp->siz)) + return; + + eprintf("%s:%d: dalloc: Memory overflow on %p, total: %zu bytes\n" + "The pointer ", file, line, dp->p, dp->siz); + if (dp->comment) + eprintf("'%s' ", dp->comment); + eprintf("was allocated in '%s' on line %d.\n", dp->file, dp->line); + pthread_mutex_unlock(&dalloc_mutex); + exit(EXIT_STATUS); +} + +size_t +dalloc_check_overflow(void) +{ + dalloc_ptr *dp; + size_t sum = 0; + + pthread_mutex_lock(&dalloc_mutex); + eprintf("Memory overflow:"); + for (dp = head; dp; dp = dp->next) { + if (!OVERFLOW(dp->p, dp->siz)) + continue; + + sum++; + eprintf("\n%s:%d: %p, total: %zu bytes", + dp->file, dp->line, dp->p, dp->siz); + if (dp->comment) + eprintf(" /* %s */", dp->comment); + } + pthread_mutex_unlock(&dalloc_mutex); + + if (sum == 0) + eprintf(" 0 overflow :)\n"); + else + eprintf("\nTotal overflow: %zu\n", sum); + + return sum; +} + +void +dalloc_check_free(void) +{ + dalloc_ptr *dp; + size_t n = 0, sum = 0; + + pthread_mutex_lock(&dalloc_mutex); + eprintf("Memory allocated and not freed:"); + for (dp = head; dp; dp = dp->next) { + if (dp->ignored) + continue; + + n++; + sum += dp->siz; + eprintf("\n%s:%d: %p, %zu bytes", + dp->file, dp->line, dp->p, dp->siz); + if (dp->comment) + eprintf(" /* %s */", dp->comment); + } + pthread_mutex_unlock(&dalloc_mutex); + + if (sum == 0) + eprintf(" 0 byte :)\n"); + else + eprintf("\nTotal: %zu bytes, %zu pointers\n", sum, n); +} + +void +dalloc_check_all(void) +{ + dalloc_check_overflow(); + dalloc_check_free(); +} + +void +_dalloc_ignore(void *p, char *file, int line) +{ + dalloc_ptr *dp; + + pthread_mutex_lock(&dalloc_mutex); + dp = find_ptr(p, file, line); + dp->ignored = 1; + pthread_mutex_unlock(&dalloc_mutex); +} + +void +_dalloc_comment(void *p, const char *comment, char *file, int line) +{ + dalloc_ptr *dp; + + if (comment == NULL) + return; + + pthread_mutex_lock(&dalloc_mutex); + dp = find_ptr(p, file, line); + free(dp->comment); + dp->comment = xstrdup(comment, file, line); + pthread_mutex_unlock(&dalloc_mutex); +} + +void +_dalloc_query(void *p, char *file, int line) +{ + dalloc_ptr *dp; + + pthread_mutex_lock(&dalloc_mutex); + dp = find_ptr(p, file, line); + fprintf(stderr, "%s:%d: dalloc: %p: %s:%d: %zu bytes", + file, line, dp->p, dp->file, dp->line, dp->siz); + if (dp->comment) + fprintf(stderr, " /* %s */", dp->comment); + fputc('\n', stderr); + pthread_mutex_unlock(&dalloc_mutex); +} + +void +_dalloc_free(void *p, char *file, int line) +{ + dalloc_ptr *dp, *prev = NULL; /* cc whines */ + + if (p == NULL) + return; + + pthread_mutex_lock(&dalloc_mutex); + for (dp = head; dp && dp->p != p; prev = dp, dp = dp->next); + if (dp == NULL) { + eprintf("%s:%d: dalloc: Unknown pointer %p\n", file, line, p); + pthread_mutex_unlock(&dalloc_mutex); + exit(EXIT_STATUS); + } + + check_overflow(dp, file, line); + + if (dp == head) + head = dp->next; + else + prev->next = dp->next; + pthread_mutex_unlock(&dalloc_mutex); + + free(dp->p); + free(dp->file); + free(dp->comment); + free(dp); +} + +void * +_dalloc_malloc(size_t siz, char *file, int line) +{ + dalloc_ptr *dp; + + if (siz == 0) { + eprintf("%s:%d: dalloc: malloc with size == 0\n", file, line); + return NULL; + } + + if (siz + OVER_ALLOC < OVER_ALLOC) { + dp = NULL; + errno = ENOMEM; + } else if ((dp = calloc(1, sizeof(*dp))) != NULL) { + dp->p = malloc(siz + OVER_ALLOC); + } + + if (dp == NULL || dp->p == NULL) { + eprintf("%s:%d: dalloc: %s\n", file, line, strerror(errno)); + exit(EXIT_STATUS); + } + + memset((char *)dp->p + siz, MAGIC_NUMBER, OVER_ALLOC); + dp->siz = siz; + dp->line = line; + + pthread_mutex_lock(&dalloc_mutex); + dp->file = xstrdup(file, file, line); + dp->next = head; + head = dp; + pthread_mutex_unlock(&dalloc_mutex); + + return dp->p; +} + +void * +_dalloc_calloc(size_t nmemb, size_t siz, char *file, int line) +{ + void *p; + + if (siz != 0 && nmemb > (size_t) -1 / siz) { + eprintf("%s:%d: dalloc: calloc: %s\n", + file, line, strerror(ENOMEM)); + exit(EXIT_STATUS); + } + + siz *= nmemb; + p = _dalloc_malloc(siz, file, line); + memset(p, 0, siz); + + return p; +} + +void * +_dalloc_realloc(void *p, size_t siz, char *file, int line) +{ + dalloc_ptr *dp; + + if (p == NULL) + return _dalloc_malloc(siz, file, line); + + if (siz == 0) { + eprintf("%s:%d: dalloc: realloc with size == 0\n", file, line); + return NULL; + } + + pthread_mutex_lock(&dalloc_mutex); + dp = find_ptr(p, file, line); + check_overflow(dp, file, line); + + if (siz + OVER_ALLOC < OVER_ALLOC) { + dp->p = NULL; + errno = ENOMEM; + } else { + dp->p = realloc(dp->p, siz + OVER_ALLOC); + } + + if (dp->p == NULL) { + eprintf("%s:%d: dalloc: %s\n", file, line, strerror(errno)); + pthread_mutex_unlock(&dalloc_mutex); + exit(EXIT_STATUS); + } + + memset((char *)dp->p + siz, MAGIC_NUMBER, OVER_ALLOC); + dp->siz = siz; + dp->line = line; + free(dp->file); + dp->file = xstrdup(file, file, line); + pthread_mutex_unlock(&dalloc_mutex); + + return dp->p; +} + +void * +_dalloc_reallocarray(void *p, size_t n, size_t s, char *file, int line) +{ + if (s != 0 && n > (size_t) -1 / s) { + eprintf("%s:%d: dalloc: reallocarray: %s\n", + file, line, strerror(ENOMEM)); + exit(EXIT_STATUS); + } + + return _dalloc_realloc(p, n * s, file, line); +} + +char * +_dalloc_strdup(const char *s, char *file, int line) +{ + char *p; + size_t siz; + + siz = strlen(s) + 1; + p = _dalloc_malloc(siz, file, line); + memcpy(p, s, siz); + + return p; +} + +char * +_dalloc_strndup(const char *s, size_t n, char *file, int line) +{ + char *p; + size_t siz; + + siz = strnlen(s, n); + p = _dalloc_malloc(siz + 1, file, line); + memcpy(p, s, siz); + p[siz] = '\0'; + + return p; +} + +#if __STDC_VERSION__ >= 199901L +int +_dalloc_vasprintf(char **p, const char *fmt, va_list ap, char *file, int line) +{ + va_list ap2; + size_t siz; + int rv; + + va_copy(ap2, ap); + rv = vsnprintf(NULL, 0, fmt, ap2); + va_end(ap2); + if (rv < 0) { + eprintf("%s:%d: dalloc: asprintf: %s\n", + file, line, strerror(errno)); + exit(EXIT_STATUS); + } + siz = (size_t)rv + 1; + *p = _dalloc_malloc(siz, file, line); + rv = vsnprintf(*p, siz, fmt, ap); + if (rv < 0) { + eprintf("%s:%d: dalloc: asprintf: %s\n", + file, line, strerror(errno)); + exit(EXIT_STATUS); + } + + return rv; +} + +int +_dalloc_asprintf(char **p, char *file, int line, const char *fmt, ...) +{ + int rv; + va_list ap; + + va_start(ap, fmt); + rv = _dalloc_vasprintf(p, fmt, ap, file, line); + va_end(ap); + + return rv; +} +#endif /* __STDC_VERSION__ >= 199901L */ diff --git a/src/dalloc.h b/src/dalloc.h new file mode 100644 index 0000000..441137f --- /dev/null +++ b/src/dalloc.h @@ -0,0 +1,70 @@ +/* + * Copyright © 2023, Ratakor <ratakor@disroot.org> + * + * This library is free software. You can redistribute it and/or modify it + * under the terms of the ISC license. See dalloc.c for details. + */ + +#ifndef DALLOC_H +#define DALLOC_H + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(DALLOC) && !defined(DALLOC_INTERNAL) +#define free(p) (_dalloc_free(p, __FILE__, __LINE__)) +#define malloc(siz) (_dalloc_malloc(siz, __FILE__, __LINE__)) +#define calloc(nmemb, siz) (_dalloc_calloc(nmemb, siz, __FILE__, __LINE__)) +#define realloc(p, siz) (_dalloc_realloc(p, siz, __FILE__, __LINE__)) +#define reallocarray(p, n, s) (_dalloc_reallocarray(p, n, s, __FILE__, __LINE__)) +#define strdup(s) (_dalloc_strdup(s, __FILE__, __LINE__)) +#define strndup(s, n) (_dalloc_strndup(s, n, __FILE__, __LINE__)) +#if __STDC_VERSION__ >= 199901L +#define vasprintf(p, fmt, ap) (_dalloc_vasprintf(p, fmt, ap, __FILE__, __LINE__)) +#define asprintf(p, ...) (_dalloc_asprintf(p, __FILE__, __LINE__, __VA_ARGS__)) +#endif /* __STDC_VERSION__ >= 199901L */ + +#define dalloc_ignore(p) (_dalloc_ignore(p, __FILE__, __LINE__)) +#define dalloc_comment(p, str) (_dalloc_comment(p, str, __FILE__, __LINE__)) +#define dalloc_query(p) (_dalloc_query(p, __FILE__, __LINE__)) +#endif /* DALLOC && !DALLOC_INTERNAL */ + +#if defined(DALLOC) || defined(DALLOC_INTERNAL) +size_t dalloc_check_overflow(void); +void dalloc_check_free(void); +void dalloc_check_all(void) __attribute__((destructor)); + +void _dalloc_ignore(void *p, char *file, int line); +void _dalloc_comment(void *p, const char *comment, char *file, int line); +void _dalloc_query(void *p, char *file, int line); +void _dalloc_free(void *p, char *file, int line); +void *_dalloc_malloc(size_t siz, char *file, int line); +void *_dalloc_calloc(size_t nmemb, size_t siz, char *file, int line); +void *_dalloc_realloc(void *p, size_t siz, char *file, int line); +void *_dalloc_reallocarray(void *p, size_t n, size_t s, char *file, int line); +char *_dalloc_strdup(const char *s, char *file, int line); +char *_dalloc_strndup(const char *s, size_t n, char *file, int line); +#if __STDC_VERSION__ >= 199901L +int _dalloc_vasprintf(char **p, const char *fmt, va_list ap, char *file, int line); +int _dalloc_asprintf(char **p, char *file, int line, const char *fmt, ...); +#endif /* __STDC_VERSION__ >= 199901L */ +#else +#define dalloc_check_overflow() 0 +#define dalloc_check_free() +#define dalloc_check_all() +#define dalloc_ignore(p) +#define dalloc_comment(p, str) +#define dalloc_query(p) +#endif /* DALLOC || DALLOC_INTERNAL */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DALLOC_H */ @@ -77,11 +77,14 @@ sighandler(int sig) } int -main(void) +main(int argc, char *argv[]) { char *src[] = { "src", "source" }; char *lb[] = { "lb", "leaderboard" }; + UNUSED(argc); + progname = argv[0]; + create_folders(); create_stats_file(); init_players(); diff --git a/src/nolan.h b/src/nolan.h index a76a17c..fd90d52 100644 --- a/src/nolan.h +++ b/src/nolan.h @@ -6,9 +6,8 @@ #include <pthread.h> #include <concord/discord.h> #include <concord/log.h> -#include <libre/ubik.h> -#include <libre/dalloc.h> +#include "dalloc.h" #include "../config.h" /* normally 50 but let's do * 3 to prevent from buffer overflow :) */ @@ -27,6 +26,12 @@ #define IMAGES_FOLDER SAVE_FOLDER "images/" #define RAIDS_FOLDER SAVE_FOLDER "raids/" #define STATS_FILE SAVE_FOLDER FILENAME + +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#define LENGTH(X) (sizeof(X) / sizeof(X[0])) +#define STRLEN(X) (sizeof(X) - 1) +#define UNUSED(X) ((void)(X)) #define VALID_STATS(X) (strchr(X, DELIM) == 0) #define U32CAST(player)\ ((uint32_t *)((char *)(player) + MAX_USERNAME_SIZ + MAX_KINGDOM_SIZ) - 2) @@ -94,11 +99,19 @@ typedef struct { bool found_in_file; } Slayer; +extern char *progname; extern Player *player_head; extern pthread_mutex_t player_mutex; extern const char *fields[24]; /* util.c */ +void warn(const char *fmt, ...); +void die(int status, const char *fmt, ...); +char *nstrchr(const char *s, int c, size_t n); +size_t ufmt(char *dst, size_t dsiz, uintmax_t n); +size_t ifmt(char *dst, size_t dsiz, intmax_t n); +size_t strlcpy(char *dst, const char *src, size_t siz); +size_t strlcat(char *dst, const char *src, size_t siz); #ifdef DALLOC #define xmalloc(siz) malloc(siz) #define xcalloc(nmemb, siz) calloc(nmemb, siz) diff --git a/src/stats.c b/src/stats.c index 7237c61..584d68a 100644 --- a/src/stats.c +++ b/src/stats.c @@ -459,9 +459,8 @@ update_players(char *buf, size_t siz, Player *new_player) player = find_player(new_player->userid); s += write_quote(buf + s, siz - s); if (player == NULL) { /* new player */ - player = memdup(new_player, sizeof(*new_player)); - if (player == NULL) - die(1, "memdup:"); + player = xmalloc(sizeof(*player)); + memcpy(player, new_player, sizeof(*player)); player->next = player_head; player_head = player; s += snprintf(buf + s, siz - s, @@ -2,11 +2,134 @@ #include <sys/stat.h> #include <errno.h> +#include <stdarg.h> #include <string.h> -#include <libre/ubik.h> #include "nolan.h" +char *progname; + +static void +vwarn(const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", progname); + + if (fmt == NULL) { + perror(NULL); + return; + } + + vfprintf(stderr, fmt, ap); + if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } +} + +void +warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); +} + +void +die(int status, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); + + exit(status); +} + +char * +nstrchr(const char *s, int c, size_t n) +{ + char *p; + + if (n == 0 || s == NULL) + return NULL; + + p = strchr(s, c); + while (--n != 0 && (p = strchr(p + 1, c)) != NULL); + + return p; +} + +size_t +ufmt(char *dst, size_t dsiz, uintmax_t n) +{ + char buf[sizeof(n) * 4], *p; + size_t sizn = 1; + + p = buf + sizeof(buf) - 1; + *p-- = '\0'; + for (;;) { + *p-- = (n % 10) + '0'; + if ((n /= 10) == 0) + break; + if ((sizn % 3) == 0) + *p-- = ','; + sizn++; + } + + return strlcpy(dst, p + 1, dsiz); +} + +size_t +ifmt(char *dst, size_t dsiz, intmax_t n) +{ + if (dsiz == 0) { + if (n < 0) + n = -n; + return ufmt(NULL, 0, (uintmax_t)n) + 1; + } + + if (n < 0) { + *dst = '-'; + n = -n; + } else { + *dst = '+'; + } + + return ufmt(dst + 1, dsiz - 1, (uintmax_t)n) + 1; +} + +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + size_t slen, len; + + slen = strlen(src); + if (siz != 0) { + len = MIN(slen, siz - 1); + memcpy(dst, src, len); + dst[len] = '\0'; + } + + return slen; +} + +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + size_t dlen; + + dlen = strlen(dst); + if (dlen >= siz) + return strlen(src) + siz; + + return dlen + strlcpy(dst + dlen, src, siz - dlen); +} + #ifndef DALLOC void * xmalloc(size_t siz) |