aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRatakor <ratakor@disroot.org>2023-07-17 00:03:12 +0200
committerRatakor <ratakor@disroot.org>2023-07-17 00:03:12 +0200
commit677a197027a04e8703613971fefc90606d3b12e6 (patch)
tree495fb945e65008751c97ea6259b744adc7c7b618
parent3984c2e6fdea72a5f04ec7c57e4c59dbaf6638ca (diff)
Add asprintf and improve header
Also added vasprintf and warnings for alloc with siz == 0.
-rw-r--r--README.md16
-rw-r--r--dalloc.c76
-rw-r--r--dalloc.h35
3 files changed, 83 insertions, 44 deletions
diff --git a/README.md b/README.md
index a967b90..a10cce3 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,22 @@
dalloc
======
-A simple, thread safe, drop-in memory allocation debugging lib for C89+
+A simple, thread safe, drop-in memory allocation debugging lib for C
Usage
-----
dalloc.c and dalloc.h should be dropped into an existing project and
compiled with the `-DDALLOC` flag to define the macro that enables dalloc.
dalloc will replace free(), malloc(), calloc(), realloc(), reallocarray(),
-strdup(), and strndup() by a more secure version that will check for buffer
-overflow and memory leak. It will also output a recap at the end of the program.
+strdup(), strndup(), vasprintf() and asprintf() by a more secure version that
+will check for buffer overflow and memory leak. It will also output a recap at
+the end of the program.
By defining `EXITSEGV` all exit() call will be replaced by a segmentation fault
which can be very useful to check where an overflow occur with a real debugger.
-strdup, strndup and reallocarray are not standard so you'll probably need to
-define `_DEFAULT_SOURCE` or equivalent to use them outside of dalloc.
+strdup, strndup, reallocarray, vasprintf and asprintf are not standard so you
+will probably need to define `_DEFAULT_SOURCE` or equivalent to use them
+outside of dalloc.
Functions
---------
@@ -43,5 +45,5 @@ When `DALLOC` is not defined this function does nothing.
Notes
-----
-An error with "Unknown pointer" is either caused by a double free or when
-freeing a pointer allocated with a function not supported by dalloc.
+An error with "Unknown pointer" can be caused by a double free or when freeing
+a pointer allocated with a function not supported by dalloc.
diff --git a/dalloc.c b/dalloc.c
index cf9f37b..bff2c0f 100644
--- a/dalloc.c
+++ b/dalloc.c
@@ -16,16 +16,17 @@
#include <errno.h>
#include <pthread.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#define DALLOC_INTERNAL
+#include "dalloc.h"
+
#define EXIT_STATUS 9
#ifdef DALLOC
-#undef DALLOC
-#include "dalloc.h"
-
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#define OVER_ALLOC 64
#define MAGIC_NUMBER 0x99
@@ -201,8 +202,11 @@ _dalloc_malloc(size_t siz, char *file, int line)
void *p = NULL;
size_t sizfname;
- if (siz == 0)
+ if (siz == 0) {
+ fprintf(stderr, "%s:%d: dalloc: malloc with size == 0\n",
+ file, line);
return NULL;
+ }
if (npointers == MAX_POINTERS) {
fprintf(stderr, "dalloc: Too much pointers (max:%d)\n",
@@ -240,8 +244,11 @@ _dalloc_calloc(size_t nmemb, size_t siz, char *file, int line)
{
void *p;
- if (nmemb == 0 || siz == 0)
+ if (nmemb == 0 || siz == 0) {
+ fprintf(stderr, "%s:%d: dalloc: calloc with size == 0\n",
+ file, line);
return NULL;
+ }
if (nmemb > -1 / siz) {
fprintf(stderr, "%s:%d: dalloc: calloc: %s\n",
@@ -314,7 +321,13 @@ _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)
{
- if (s != 0 && n > -1 / s) {
+ if (n == 0 || s == 0) {
+ fprintf(stderr, "%s:%d: dalloc: reallocarray with size == 0\n",
+ file, line);
+ return NULL;
+ }
+
+ if (n > -1 / s) {
fprintf(stderr, "%s:%d: dalloc: reallocarray: %s\n",
file, line, strerror(ENOMEM));
exit(EXIT_STATUS);
@@ -352,31 +365,44 @@ _dalloc_strndup(const char *s, size_t n, char *file, int line)
return p;
}
-#else
-
-#include "dalloc.h"
+int
+_dalloc_vasprintf(char **p, const char *fmt, va_list ap, char *file, int line)
+{
+ va_list ap2;
+ size_t siz;
+ int rv;
-#define NO_DALLOC "dalloc: Define `DALLOC` to enable dalloc"
+ va_copy(ap2, ap);
+ rv = vsnprintf(NULL, 0, fmt, ap2);
+ va_end(ap2);
+ if (rv < 0) {
+ fprintf(stderr, "%s:%d: dalloc: asprintf: %s\n",
+ file, line, strerror(errno));
+ exit(EXIT_STATUS);
+ }
+ siz = rv + 1;
+ *p = _dalloc_malloc(siz, file, line);
+ rv = vsnprintf(*p, siz, fmt, ap);
+ if (rv < 0) {
+ fprintf(stderr, "%s:%d: dalloc: asprintf: %s\n",
+ file, line, strerror(errno));
+ exit(EXIT_STATUS);
+ }
-size_t
-dalloc_check_overflow(void)
-{
- fprintf(stderr, "%s\n", NO_DALLOC);
- return 0;
+ return rv;
}
-void
-dalloc_check_free(void)
+int
+_dalloc_asprintf(char **p, char *file, int line, const char *fmt, ...)
{
- fprintf(stderr, "%s\n", NO_DALLOC);
- return;
-}
+ int rv;
+ va_list ap;
-void
-dalloc_check_all(void)
-{
- fprintf(stderr, "%s\n", NO_DALLOC);
- return;
+ va_start(ap, fmt);
+ rv = _dalloc_vasprintf(p, fmt, ap, file, line);
+ va_end(ap);
+
+ return rv;
}
#endif /* DALLOC */
diff --git a/dalloc.h b/dalloc.h
index 7d8376a..69a45b2 100644
--- a/dalloc.h
+++ b/dalloc.h
@@ -8,6 +8,7 @@
#ifndef DALLOC_H
#define DALLOC_H
+#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@@ -15,30 +16,25 @@
extern "C" {
#endif /* __cplusplus */
-#ifdef DALLOC
+#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) (_dallloc_strndup(s, n, __FILE__, __LINE__))
+#define strndup(s, n) (_dalloc_strndup(s, n, __FILE__, __LINE__))
+#define vasprintf(p, fmt, ap) (_dalloc_vasprintf(p, fmt, ap, __FILE__, __LINE__))
+#define asprintf(p, fmt, ...) (_dalloc_asprintf(p, __FILE__, __LINE__, fmt, __VA_ARGS__))
#define dalloc_ignore(p) (_dalloc_ignore(p, __FILE__, __LINE__))
-#define dalloc_comment(p, com) (_dalloc_comment(p, com, __FILE__, __LINE__))
-#else
-#define dalloc_ignore(p)
-#define dalloc_comment(p, comment)
-#endif /* DALLOC */
-
-#ifdef EXITSEGV
-#define exit(dummy) (exitsegv(dummy))
-#endif /* EXITSEGV */
+#define dalloc_comment(p, str) (_dalloc_comment(p, str, __FILE__, __LINE__))
+#endif /* DALLOC && !DALLOC_INTERNAL */
+#ifdef DALLOC
size_t dalloc_check_overflow(void);
void dalloc_check_free(void);
void dalloc_check_all(void);
-void dalloc_sighandler(int sig);
void _dalloc_ignore(void *p, char *file, int line);
void _dalloc_comment(void *p, const char *comment, char *file, int line);
@@ -49,7 +45,22 @@ 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);
+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, ...);
+#else
+#define _NO_DALLOC "dalloc: Define `DALLOC` to enable dalloc"
+#define dalloc_ignore(p)
+#define dalloc_comment(p, str)
+#define dalloc_check_overflow() (fprintf(stderr, "%s\n", _NO_DALLOC), 0)
+#define dalloc_check_free() (fprintf(stderr, "%s\n", _NO_DALLOC))
+#define dalloc_check_all() (fprintf(stderr, "%s\n", _NO_DALLOC))
+#endif /* DALLOC */
+#ifdef EXITSEGV
+#define exit(dummy) (exitsegv(dummy))
+#endif /* EXITSEGV */
+
+void dalloc_sighandler(int sig);
void exitsegv(int dummy);
#ifdef __cplusplus