summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2017-07-03 13:07:29 +0100
committerRobin Watts <Robin.Watts@artifex.com>2017-07-03 14:17:54 +0100
commit9616a3d9407973c8f527ab209d6d6bc88faab281 (patch)
tree74967f54141bd6bcf3c7a465fd15dbf39dbb0b1f
parentf01b9010625977956fc27a384335c9599681bcbf (diff)
downloadmupdf-9616a3d9407973c8f527ab209d6d6bc88faab281.tar.xz
Memento: pointer checking functions.
Add some helpful functions for doing quick checks on pointer validity. Use these in the reference counting functions.
-rw-r--r--include/mupdf/memento.h78
-rw-r--r--source/fitz/memento.c186
2 files changed, 236 insertions, 28 deletions
diff --git a/include/mupdf/memento.h b/include/mupdf/memento.h
index ee9bf4fb..0776860f 100644
--- a/include/mupdf/memento.h
+++ b/include/mupdf/memento.h
@@ -217,11 +217,22 @@ void *Memento_calloc(size_t, size_t);
void Memento_info(void *addr);
void Memento_listBlockInfo(void);
+void *Memento_takeByteRef(void *blk);
+void *Memento_dropByteRef(void *blk);
+void *Memento_takeShortRef(void *blk);
+void *Memento_dropShortRef(void *blk);
+void *Memento_takeIntRef(void *blk);
+void *Memento_dropIntRef(void *blk);
void *Memento_takeRef(void *blk);
void *Memento_dropRef(void *blk);
void *Memento_adjustRef(void *blk, int adjust);
void *Memento_reference(void *blk);
+int Memento_checkPointerOrNull(void *blk);
+int Memento_checkBytePointerOrNull(void *blk);
+int Memento_checkShortPointerOrNull(void *blk);
+int Memento_checkIntPointerOrNull(void *blk);
+
void Memento_startLeaking(void);
void Memento_stopLeaking(void);
@@ -243,34 +254,45 @@ void Memento_fin(void);
#define Memento_realloc MEMENTO_UNDERLYING_REALLOC
#define Memento_calloc MEMENTO_UNDERLYING_CALLOC
-#define Memento_checkBlock(A) 0
-#define Memento_checkAllMemory() 0
-#define Memento_check() 0
-#define Memento_setParanoia(A) 0
-#define Memento_paranoidAt(A) 0
-#define Memento_breakAt(A) 0
-#define Memento_breakOnFree(A) 0
-#define Memento_breakOnRealloc(A) 0
-#define Memento_getBlockNum(A) 0
-#define Memento_find(A) 0
-#define Memento_breakpoint() do {} while (0)
-#define Memento_failAt(A) 0
-#define Memento_failThisEvent() 0
-#define Memento_listBlocks() do {} while (0)
-#define Memento_listNewBlocks() do {} while (0)
-#define Memento_setMax(A) 0
-#define Memento_stats() do {} while (0)
-#define Memento_label(A,B) (A)
-#define Memento_info(A) do {} while (0)
-#define Memento_listBlockInfo() do {} while (0)
-#define Memento_takeRef(A) (A)
-#define Memento_dropRef(A) (A)
-#define Memento_adjustRef(A,V) (A)
-#define Memento_reference(A) (A)
-#define Memento_tick() do {} while (0)
-#define Memento_startLeaking() do {} while (0)
-#define Memento_stopLeaking() do {} while (0)
-#define Memento_fin() do {} while (0)
+#define Memento_checkBlock(A) 0
+#define Memento_checkAllMemory() 0
+#define Memento_check() 0
+#define Memento_setParanoia(A) 0
+#define Memento_paranoidAt(A) 0
+#define Memento_breakAt(A) 0
+#define Memento_breakOnFree(A) 0
+#define Memento_breakOnRealloc(A) 0
+#define Memento_getBlockNum(A) 0
+#define Memento_find(A) 0
+#define Memento_breakpoint() do {} while (0)
+#define Memento_failAt(A) 0
+#define Memento_failThisEvent() 0
+#define Memento_listBlocks() do {} while (0)
+#define Memento_listNewBlocks() do {} while (0)
+#define Memento_setMax(A) 0
+#define Memento_stats() do {} while (0)
+#define Memento_label(A,B) (A)
+#define Memento_info(A) do {} while (0)
+#define Memento_listBlockInfo() do {} while (0)
+#define Memento_takeByteRef(A) (A)
+#define Memento_dropByteRef(A) (A)
+#define Memento_takeShortRef(A) (A)
+#define Memento_dropShortRef(A) (A)
+#define Memento_takeIntRef(A) (A)
+#define Memento_dropIntRef(A) (A)
+#define Memento_takeRef(A) (A)
+#define Memento_dropRef(A) (A)
+#define Memento_adjustRef(A,V) (A)
+#define Memento_reference(A) (A)
+#define Memento_checkPointerOrNull(A) 0
+#define Memento_checkBytePointerOrNull(A) 0
+#define Memento_checkShortPointerOrNull(A) 0
+#define Memento_checkIntPointerOrNull(A) 0
+
+#define Memento_tick() do {} while (0)
+#define Memento_startLeaking() do {} while (0)
+#define Memento_stopLeaking() do {} while (0)
+#define Memento_fin() do {} while (0)
#endif /* MEMENTO */
diff --git a/source/fitz/memento.c b/source/fitz/memento.c
index 330fc359..a71dce7f 100644
--- a/source/fitz/memento.c
+++ b/source/fitz/memento.c
@@ -57,6 +57,26 @@ int atexit(void (*)(void));
#include <stdio.h>
#endif
+#define UB(x) ((intptr_t)((x) & 0xFF))
+#define B2I(x) (UB(x) | (UB(x)<<8) | (UB(x)<<16) | (UB(x)<<24))
+#define B2P(x) ((void *)(B2I(x) | ((B2I(x)<<16)<<16)))
+#define MEMENTO_PREFILL_UBYTE ((unsigned char)(MEMENTO_PREFILL))
+#define MEMENTO_PREFILL_USHORT (((unsigned short)MEMENTO_PREFILL_UBYTE) | (((unsigned short)MEMENTO_PREFILL_UBYTE)<<8))
+#define MEMENTO_PREFILL_UINT (((unsigned int)MEMENTO_PREFILL_USHORT) | (((unsigned int)MEMENTO_PREFILL_USHORT)<<16))
+#define MEMENTO_PREFILL_PTR (void *)(((uintptr_t)MEMENTO_PREFILL_UINT) | ((((uintptr_t)MEMENTO_PREFILL_UINT)<<16)<<16))
+#define MEMENTO_POSTFILL_UBYTE ((unsigned char)(MEMENTO_POSTFILL))
+#define MEMENTO_POSTFILL_USHORT (((unsigned short)MEMENTO_POSTFILL_UBYTE) | (((unsigned short)MEMENTO_POSTFILL_UBYTE)<<8))
+#define MEMENTO_POSTFILL_UINT (((unsigned int)MEMENTO_POSTFILL_USHORT) | (((unsigned int)MEMENTO_POSTFILL_USHORT)<<16))
+#define MEMENTO_POSTFILL_PTR (void *)(((uintptr_t)MEMENTO_POSTFILL_UINT) | ((((uintptr_t)MEMENTO_POSTFILL_UINT)<<16)<<16))
+#define MEMENTO_ALLOCFILL_UBYTE ((unsigned char)(MEMENTO_ALLOCFILL))
+#define MEMENTO_ALLOCFILL_USHORT (((unsigned short)MEMENTO_ALLOCFILL_UBYTE) | (((unsigned short)MEMENTO_ALLOCFILL_UBYTE)<<8))
+#define MEMENTO_ALLOCFILL_UINT (((unsigned int)MEMENTO_ALLOCFILL_USHORT) | (((unsigned int)MEMENTO_ALLOCFILL_USHORT)<<16))
+#define MEMENTO_ALLOCFILL_PTR (void *)(((uintptr_t)MEMENTO_ALLOCFILL_UINT) | ((((uintptr_t)MEMENTO_ALLOCFILL_UINT)<<16)<<16))
+#define MEMENTO_FREEFILL_UBYTE ((unsigned char)(MEMENTO_FREEFILL))
+#define MEMENTO_FREEFILL_USHORT (((unsigned short)MEMENTO_FREEFILL_UBYTE) | (((unsigned short)MEMENTO_FREEFILL_UBYTE)<<8))
+#define MEMENTO_FREEFILL_UINT (((unsigned int)MEMENTO_FREEFILL_USHORT) | (((unsigned int)MEMENTO_FREEFILL_USHORT)<<16))
+#define MEMENTO_FREEFILL_PTR (void *)(((uintptr_t)MEMENTO_FREEFILL_UINT) | ((((uintptr_t)MEMENTO_FREEFILL_UINT)<<16)<<16))
+
#ifdef MEMENTO
#ifndef MEMENTO_CPP_EXTRAS_ONLY
@@ -799,6 +819,18 @@ static void Memento_showStacktrace(void **stack, int numberOfFrames)
}
#endif /* MEMENTO_STACKTRACE_METHOD */
+void Memento_backtrace()
+{
+#ifdef MEMENTO_STACKTRACE_METHOD
+ void *stack[MEMENTO_BACKTRACE_MAX];
+ int count;
+ int skip;
+
+ count = Memento_getStacktrace(stack, &skip);
+ Memento_showStacktrace(&stack[skip], count - skip);
+#endif
+}
+
#ifdef MEMENTO_DETAILS
static void Memento_storeDetails(Memento_BlkHeader *head, int type)
{
@@ -1869,6 +1901,116 @@ static void do_reference(Memento_BlkHeader *blk, int event)
#endif /* MEMENTO_DETAILS */
}
+int Memento_checkPointerOrNull(void *blk)
+{
+ if (blk == NULL)
+ return 0;
+ if (blk == MEMENTO_PREFILL_PTR)
+ fprintf(stderr, "Prefill value found as pointer - buffer underrun?\n");
+ else if (blk == MEMENTO_POSTFILL_PTR)
+ fprintf(stderr, "Postfill value found as pointer - buffer overrun?\n");
+ else if (blk == MEMENTO_ALLOCFILL_PTR)
+ fprintf(stderr, "Allocfill value found as pointer - use of uninitialised value?\n");
+ else if (blk == MEMENTO_FREEFILL_PTR)
+ fprintf(stderr, "Allocfill value found as pointer - use after free?\n");
+ else
+ return 0;
+#ifdef MEMENTO_DETAILS
+ fprintf(stderr, "Current backtrace:\n");
+ Memento_backtrace();
+ fprintf(stderr, "History:\n");
+ Memento_info(blk);
+#endif
+ return 1;
+}
+
+int Memento_checkBytePointerOrNull(void *blk)
+{
+ unsigned char i;
+ if (blk == NULL)
+ return 0;
+ Memento_checkPointerOrNull(blk);
+
+ i = *(unsigned int *)blk;
+
+ if (i == MEMENTO_PREFILL_UBYTE)
+ fprintf(stderr, "Prefill value found - buffer underrun?\n");
+ else if (i == MEMENTO_POSTFILL_UBYTE)
+ fprintf(stderr, "Postfill value found - buffer overrun?\n");
+ else if (i == MEMENTO_ALLOCFILL_UBYTE)
+ fprintf(stderr, "Allocfill value found - use of uninitialised value?\n");
+ else if (i == MEMENTO_FREEFILL_UBYTE)
+ fprintf(stderr, "Allocfill value found - use after free?\n");
+ else
+ return 0;
+#ifdef MEMENTO_DETAILS
+ fprintf(stderr, "Current backtrace:\n");
+ Memento_backtrace();
+ fprintf(stderr, "History:\n");
+ Memento_info(blk);
+#endif
+ Memento_breakpoint();
+ return 1;
+}
+
+int Memento_checkShortPointerOrNull(void *blk)
+{
+ unsigned short i;
+ if (blk == NULL)
+ return 0;
+ Memento_checkPointerOrNull(blk);
+
+ i = *(unsigned short *)blk;
+
+ if (i == MEMENTO_PREFILL_USHORT)
+ fprintf(stderr, "Prefill value found - buffer underrun?\n");
+ else if (i == MEMENTO_POSTFILL_USHORT)
+ fprintf(stderr, "Postfill value found - buffer overrun?\n");
+ else if (i == MEMENTO_ALLOCFILL_USHORT)
+ fprintf(stderr, "Allocfill value found - use of uninitialised value?\n");
+ else if (i == MEMENTO_FREEFILL_USHORT)
+ fprintf(stderr, "Allocfill value found - use after free?\n");
+ else
+ return 0;
+#ifdef MEMENTO_DETAILS
+ fprintf(stderr, "Current backtrace:\n");
+ Memento_backtrace();
+ fprintf(stderr, "History:\n");
+ Memento_info(blk);
+#endif
+ Memento_breakpoint();
+ return 1;
+}
+
+int Memento_checkIntPointerOrNull(void *blk)
+{
+ unsigned int i;
+ if (blk == NULL)
+ return 0;
+ Memento_checkPointerOrNull(blk);
+
+ i = *(unsigned int *)blk;
+
+ if (i == MEMENTO_PREFILL_UINT)
+ fprintf(stderr, "Prefill value found - buffer underrun?\n");
+ else if (i == MEMENTO_POSTFILL_UINT)
+ fprintf(stderr, "Postfill value found - buffer overrun?\n");
+ else if (i == MEMENTO_ALLOCFILL_UINT)
+ fprintf(stderr, "Allocfill value found - use of uninitialised value?\n");
+ else if (i == MEMENTO_FREEFILL_UINT)
+ fprintf(stderr, "Allocfill value found - use after free?\n");
+ else
+ return 0;
+#ifdef MEMENTO_DETAILS
+ fprintf(stderr, "Current backtrace:\n");
+ Memento_backtrace();
+ fprintf(stderr, "History:\n");
+ Memento_info(blk);
+#endif
+ Memento_breakpoint();
+ return 1;
+}
+
static void *do_takeRef(void *blk)
{
if (blk)
@@ -1876,10 +2018,33 @@ static void *do_takeRef(void *blk)
return blk;
}
+void *Memento_takeByteRef(void *blk)
+{
+ (void)Memento_checkBytePointerOrNull(blk);
+
+ return Memento_takeRef(blk);
+}
+
+void *Memento_takeShortRef(void *blk)
+{
+ (void)Memento_checkShortPointerOrNull(blk);
+
+ return Memento_takeRef(blk);
+}
+
+void *Memento_takeIntRef(void *blk)
+{
+ (void)Memento_checkIntPointerOrNull(blk);
+
+ return Memento_takeRef(blk);
+}
+
void *Memento_takeRef(void *blk)
{
if (Memento_event()) Memento_breakpoint();
+ Memento_checkIntPointerOrNull(blk);
+
return do_takeRef(blk);
}
@@ -1890,6 +2055,27 @@ static void *do_dropRef(void *blk)
return blk;
}
+void *Memento_dropByteRef(void *blk)
+{
+ Memento_checkBytePointerOrNull(blk);
+
+ return Memento_dropRef(blk);
+}
+
+void *Memento_dropShortRef(void *blk)
+{
+ Memento_checkShortPointerOrNull(blk);
+
+ return Memento_dropRef(blk);
+}
+
+void *Memento_dropIntRef(void *blk)
+{
+ Memento_checkIntPointerOrNull(blk);
+
+ return Memento_dropRef(blk);
+}
+
void *Memento_dropRef(void *blk)
{
if (Memento_event()) Memento_breakpoint();