forked from lda/telodendria
Add sane default memory hook to Cytoplasm, fix more leaks in json.
This commit is contained in:
parent
e22cf38eac
commit
2693b89598
6 changed files with 76 additions and 4 deletions
|
@ -124,7 +124,6 @@ LogConfigFree(LogConfig * config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_destroy(&config->lock);
|
pthread_mutex_destroy(&config->lock);
|
||||||
Free(config->tsFmt);
|
|
||||||
Free(config);
|
Free(config);
|
||||||
|
|
||||||
if (config == globalConfig)
|
if (config == globalConfig)
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#include <Int.h>
|
#include <Int.h>
|
||||||
|
@ -154,7 +157,7 @@ MemoryDelete(MemoryInfo * a)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
MemoryCheck(MemoryInfo *a)
|
MemoryCheck(MemoryInfo * a)
|
||||||
{
|
{
|
||||||
if (MEM_BOUND_LOWER(a->pointer) != MEM_BOUND ||
|
if (MEM_BOUND_LOWER(a->pointer) != MEM_BOUND ||
|
||||||
MEM_BOUND_UPPER(a->pointer, a->size - (2 * sizeof(MEM_BOUND_TYPE))) != MEM_BOUND)
|
MEM_BOUND_UPPER(a->pointer, a->size - (2 * sizeof(MEM_BOUND_TYPE))) != MEM_BOUND)
|
||||||
|
@ -458,6 +461,64 @@ void
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
HexPtr(unsigned long ptr, char *out, size_t len)
|
||||||
|
{
|
||||||
|
size_t i = len - 1;
|
||||||
|
size_t j = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
out[i] = "0123456789abcdef"[ptr % 16];
|
||||||
|
i--;
|
||||||
|
ptr /= 16;
|
||||||
|
} while (ptr > 0);
|
||||||
|
|
||||||
|
while (++i < len)
|
||||||
|
{
|
||||||
|
out[j++] = out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[j] = '\0';
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MemoryDefaultHook(MemoryAction a, MemoryInfo * i, void *args)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
unsigned long ptr = (unsigned long) MemoryInfoGetPointer(i);
|
||||||
|
|
||||||
|
size_t len = HexPtr(ptr, buf, sizeof(buf));
|
||||||
|
|
||||||
|
(void) args;
|
||||||
|
|
||||||
|
switch (a)
|
||||||
|
{
|
||||||
|
case MEMORY_BAD_POINTER:
|
||||||
|
write(STDERR_FILENO, "Bad pointer: 0x", 15);
|
||||||
|
break;
|
||||||
|
case MEMORY_CORRUPTED:
|
||||||
|
write(STDERR_FILENO, "Corrupted block: 0x", 19);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(STDERR_FILENO, buf, len);
|
||||||
|
write(STDERR_FILENO, " to 0x", 6);
|
||||||
|
len = HexPtr(MemoryInfoGetSize(i), buf, sizeof(buf));
|
||||||
|
write(STDERR_FILENO, buf, len);
|
||||||
|
write(STDERR_FILENO, " bytes at ", 10);
|
||||||
|
write(STDERR_FILENO, MemoryInfoGetFile(i), strlen(MemoryInfoGetFile(i)));
|
||||||
|
write(STDERR_FILENO, ":0x", 3);
|
||||||
|
len = HexPtr(MemoryInfoGetLine(i), buf, sizeof(buf));
|
||||||
|
write(STDERR_FILENO, buf, len);
|
||||||
|
write(STDERR_FILENO, "\n", 1);
|
||||||
|
raise(SIGSEGV);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MemoryHexDump(MemoryInfo * info, void (*printFunc) (size_t, char *, char *, void *), void *args)
|
MemoryHexDump(MemoryInfo * info, void (*printFunc) (size_t, char *, char *, void *), void *args)
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,6 +70,8 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
MainArgs args;
|
MainArgs args;
|
||||||
|
|
||||||
|
MemoryHook(MemoryDefaultHook, NULL);
|
||||||
|
|
||||||
args.args = NULL;
|
args.args = NULL;
|
||||||
args.env = NULL;
|
args.env = NULL;
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,15 @@ extern void MemoryIterate(void (*) (MemoryInfo *, void *), void *);
|
||||||
*/
|
*/
|
||||||
extern void MemoryHook(void (*) (MemoryAction, MemoryInfo *, void *), void *);
|
extern void MemoryHook(void (*) (MemoryAction, MemoryInfo *, void *), void *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default memory hook, which has sane behavior and is installed
|
||||||
|
* at runtime. This function does not use any memory on the heap,
|
||||||
|
* except for the MemoryInfo passed to it, which it assumes to be
|
||||||
|
* valid. Everything else happens on the stack only, to ensure that
|
||||||
|
* the hook doesn't make any memory problems worse.
|
||||||
|
*/
|
||||||
|
extern void MemoryDefaultHook(MemoryAction, MemoryInfo *, void *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read over the block of memory represented by the given memory info
|
* Read over the block of memory represented by the given memory info
|
||||||
* structure and generate a hexadecimal and ASCII string for each
|
* structure and generate a hexadecimal and ASCII string for each
|
||||||
|
|
2
TODO.txt
2
TODO.txt
|
@ -28,7 +28,7 @@ Milestone: v0.3.0
|
||||||
[x] hdoc(1) and hdoc(5)
|
[x] hdoc(1) and hdoc(5)
|
||||||
[x] Fix memory leaks in hdoc
|
[x] Fix memory leaks in hdoc
|
||||||
[x] Detect memory write out of bounds
|
[x] Detect memory write out of bounds
|
||||||
[ ] Add a sane default memory hook
|
[x] Add a sane default memory hook
|
||||||
|
|
||||||
Milestone: v0.4.0
|
Milestone: v0.4.0
|
||||||
-----------------
|
-----------------
|
||||||
|
|
|
@ -223,7 +223,7 @@ Main(Array * args)
|
||||||
switch (flag)
|
switch (flag)
|
||||||
{
|
{
|
||||||
case FLAG_SELECT:
|
case FLAG_SELECT:
|
||||||
query(input, json);
|
query(input, json); /* This will implicitly free json */
|
||||||
break;
|
break;
|
||||||
case FLAG_ENCODE:
|
case FLAG_ENCODE:
|
||||||
encode(input);
|
encode(input);
|
||||||
|
@ -231,6 +231,7 @@ Main(Array * args)
|
||||||
default:
|
default:
|
||||||
JsonEncode(json, StreamStdout(), JSON_PRETTY);
|
JsonEncode(json, StreamStdout(), JSON_PRETTY);
|
||||||
StreamPutc(StreamStdout(), '\n');
|
StreamPutc(StreamStdout(), '\n');
|
||||||
|
JsonFree(json);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue