]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add GODEBUG invalidptr setting
authorRuss Cox <rsc@golang.org>
Wed, 29 Oct 2014 01:53:31 +0000 (21:53 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 29 Oct 2014 01:53:31 +0000 (21:53 -0400)
Fixes #8861.
Fixes #8911.

LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/165780043

src/runtime/extern.go
src/runtime/mgc0.c
src/runtime/runtime.c
src/runtime/runtime.h
src/runtime/stack.c

index b8db5d0c4b7658f2299277bbb05f0268c0496fe6..1b8052bb563d7e6abc540cfffa093ac5e539ee81 100644 (file)
@@ -39,6 +39,12 @@ a comma-separated list of name=val pairs. Supported names are:
        gcdead: setting gcdead=1 causes the garbage collector to clobber all stack slots
        that it thinks are dead.
 
+       invalidptr: defaults to invalidptr=1, causing the garbage collector and stack
+       copier to crash the program if an invalid pointer value (for example, 1)
+       is found in a pointer-typed location. Setting invalidptr=0 disables this check.
+       This should only be used as a temporary workaround to diagnose buggy code.
+       The real fix is to not store integers in pointer-typed locations.
+
        scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit
        detailed multiline info every X milliseconds, describing state of the scheduler,
        processors, threads and goroutines.
index cba2beaa7465328dfe0bcdc7d75c75f21337a72e..1b41bf9a79419627c791092102922c05e737f57b 100644 (file)
@@ -330,7 +330,7 @@ scanblock(byte *b, uintptr n, byte *ptrmask)
                        if(obj == nil)
                                continue;
                        if(obj < arena_start || obj >= arena_used) {
-                               if((uintptr)obj < PhysPageSize) {
+                               if((uintptr)obj < PhysPageSize && runtime·invalidptr) {
                                        s = nil;
                                        goto badobj;
                                }
@@ -375,7 +375,7 @@ scanblock(byte *b, uintptr n, byte *ptrmask)
                                        else
                                                runtime·printf(" span=%p-%p-%p state=%d\n", (uintptr)s->start<<PageShift, s->limit, (uintptr)(s->start+s->npages)<<PageShift, s->state);
                                        if(ptrmask != nil)
-                                               runtime·throw("bad pointer");
+                                               runtime·throw("invalid heap pointer");
                                        // Add to badblock list, which will cause the garbage collection
                                        // to keep repeating until it has traced the chain of pointers
                                        // leading to obj all the way back to a root.
index b3503fb909a2777fbddf3bee15d9e02783f277c9..c823691ec5a178ca27f1ef5f2d60cdede2be83a1 100644 (file)
@@ -276,9 +276,13 @@ struct DbgVar
        int32*  value;
 };
 
+// Do we report invalid pointers found during stack or heap scans?
+int32 runtime·invalidptr = 1;
+
 #pragma dataflag NOPTR /* dbgvar has no heap pointers */
 static DbgVar dbgvar[] = {
        {"allocfreetrace", &runtime·debug.allocfreetrace},
+       {"invalidptr", &runtime·invalidptr},
        {"efence", &runtime·debug.efence},
        {"gctrace", &runtime·debug.gctrace},
        {"gcdead", &runtime·debug.gcdead},
index a84a32525eb2b5ea619a1f66d5d26e8b2740bfd6..2a607400636ad72d80c5bfd95bba92e8ca2980f8 100644 (file)
@@ -657,6 +657,8 @@ enum {
 byte*  runtime·startup_random_data;
 uint32 runtime·startup_random_data_len;
 
+int32  runtime·invalidptr;
+
 enum {
        // hashinit wants this many random bytes
        HashRandomBytes = 32
index e402691f450d1c338b79e720ba0edc914e447fdd..ed8f4f872799be664a90c501de68094a8af7b07d 100644 (file)
@@ -401,12 +401,12 @@ adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f)
                        break;
                case BitsPointer:
                        p = scanp[i];
-                       if(f != nil && (byte*)0 < p && (p < (byte*)PageSize || (uintptr)p == PoisonGC || (uintptr)p == PoisonStack)) {
+                       if(f != nil && (byte*)0 < p && (p < (byte*)PageSize && runtime·invalidptr || (uintptr)p == PoisonGC || (uintptr)p == PoisonStack)) {
                                // Looks like a junk value in a pointer slot.
                                // Live analysis wrong?
                                g->m->traceback = 2;
                                runtime·printf("runtime: bad pointer in frame %s at %p: %p\n", runtime·funcname(f), &scanp[i], p);
-                               runtime·throw("bad pointer!");
+                               runtime·throw("invalid stack pointer");
                        }
                        if(minp <= p && p < maxp) {
                                if(StackDebug >= 3)