mirror of
https://github.com/golang/go
synced 2024-11-25 10:07:56 -07:00
bug162, over and over
R=ken OCL=35919 CL=35919
This commit is contained in:
parent
d6b64f273f
commit
02fd255a14
@ -610,6 +610,17 @@ agen(Node *n, Node *res)
|
||||
case ODOTPTR:
|
||||
cgen(nl, res);
|
||||
if(n->xoffset != 0) {
|
||||
// explicit check for nil if struct is large enough
|
||||
// that we might derive too big a pointer.
|
||||
if(nl->type->type->width >= unmappedzero) {
|
||||
regalloc(&n1, types[tptr], res);
|
||||
gmove(res, &n1);
|
||||
n1.op = OINDREG;
|
||||
n1.type = types[TUINT8];
|
||||
n1.xoffset = 0;
|
||||
gins(ATESTB, nodintconst(0), &n1);
|
||||
regfree(&n1);
|
||||
}
|
||||
nodconst(&n1, types[TINT64], n->xoffset);
|
||||
gins(optoas(OADD, types[tptr]), &n1, res);
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ EXTERN Node* deferreturn;
|
||||
EXTERN Node* throwindex;
|
||||
EXTERN Node* throwslice;
|
||||
EXTERN Node* throwreturn;
|
||||
EXTERN vlong unmappedzero;
|
||||
|
||||
/*
|
||||
* gen.c
|
||||
@ -92,7 +93,7 @@ void sgen(Node*, Node*, int32);
|
||||
void gmove(Node*, Node*);
|
||||
Prog* gins(int, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void naddr(Node*, Addr*);
|
||||
void naddr(Node*, Addr*, int);
|
||||
void cgen_aret(Node*, Node*);
|
||||
int cgen_inline(Node*, Node*);
|
||||
void restx(Node*, Node*);
|
||||
|
@ -1137,7 +1137,7 @@ cgen_inline(Node *n, Node *res)
|
||||
goto no;
|
||||
if(!n->left->addable)
|
||||
goto no;
|
||||
if(strcmp(n->left->sym->package, "sys") != 0)
|
||||
if(strcmp(n->left->sym->package, "runtime") != 0)
|
||||
goto no;
|
||||
if(strcmp(n->left->sym->name, "slicearray") == 0)
|
||||
goto slicearray;
|
||||
@ -1215,6 +1215,16 @@ slicearray:
|
||||
}
|
||||
gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
|
||||
|
||||
// if slice could be too big, dereference to
|
||||
// catch nil array pointer.
|
||||
if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
|
||||
n2 = nodes[0];
|
||||
n2.xoffset = 0;
|
||||
n2.op = OINDREG;
|
||||
n2.type = types[TUINT8];
|
||||
gins(ATESTB, nodintconst(0), &n2);
|
||||
}
|
||||
|
||||
for(i=0; i<5; i++) {
|
||||
if(nodes[i].op == OREGISTER)
|
||||
regfree(&nodes[i]);
|
||||
@ -1241,6 +1251,16 @@ arraytoslice:
|
||||
n2.xoffset += Array_array;
|
||||
gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
|
||||
|
||||
// if slice could be too big, dereference to
|
||||
// catch nil array pointer.
|
||||
if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
|
||||
n2 = nodes[0];
|
||||
n2.xoffset = 0;
|
||||
n2.op = OINDREG;
|
||||
n2.type = types[TUINT8];
|
||||
gins(ATESTB, nodintconst(0), &n2);
|
||||
}
|
||||
|
||||
for(i=0; i<2; i++) {
|
||||
if(nodes[i].op == OREGISTER)
|
||||
regfree(&nodes[i]);
|
||||
|
@ -30,6 +30,10 @@
|
||||
|
||||
#include "gg.h"
|
||||
|
||||
// TODO(rsc): Can make this bigger if we move
|
||||
// the text segment up higher in 6l for all GOOS.
|
||||
vlong unmappedzero = 4096;
|
||||
|
||||
void
|
||||
clearp(Prog *p)
|
||||
{
|
||||
@ -832,6 +836,7 @@ gins(int as, Node *f, Node *t)
|
||||
// Node nod;
|
||||
// int32 v;
|
||||
Prog *p;
|
||||
Addr af, at;
|
||||
|
||||
// if(f != N && f->op == OINDEX) {
|
||||
// regalloc(&nod, ®node, Z);
|
||||
@ -861,22 +866,46 @@ gins(int as, Node *f, Node *t)
|
||||
return nil;
|
||||
}
|
||||
|
||||
memset(&af, 0, sizeof af);
|
||||
memset(&at, 0, sizeof at);
|
||||
if(f != N)
|
||||
naddr(f, &af, 1);
|
||||
if(t != N)
|
||||
naddr(t, &at, 1);
|
||||
p = prog(as);
|
||||
if(f != N)
|
||||
naddr(f, &p->from);
|
||||
p->from = af;
|
||||
if(t != N)
|
||||
naddr(t, &p->to);
|
||||
p->to = at;
|
||||
if(debug['g'])
|
||||
print("%P\n", p);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
checkoffset(Addr *a, int canemitcode)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
if(a->offset < unmappedzero)
|
||||
return;
|
||||
if(!canemitcode)
|
||||
fatal("checkoffset %#llx, cannot emit code", a->offset);
|
||||
|
||||
// cannot rely on unmapped nil page at 0 to catch
|
||||
// reference with large offset. instead, emit explicit
|
||||
// test of 0(reg).
|
||||
p = gins(ATESTB, nodintconst(0), N);
|
||||
p->to = *a;
|
||||
p->to.offset = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* generate code to compute n;
|
||||
* make a refer to result.
|
||||
*/
|
||||
void
|
||||
naddr(Node *n, Addr *a)
|
||||
naddr(Node *n, Addr *a, int canemitcode)
|
||||
{
|
||||
a->scale = 0;
|
||||
a->index = D_NONE;
|
||||
@ -920,6 +949,7 @@ naddr(Node *n, Addr *a)
|
||||
a->type = n->val.u.reg+D_INDIR;
|
||||
a->sym = n->sym;
|
||||
a->offset = n->xoffset;
|
||||
checkoffset(a, canemitcode);
|
||||
break;
|
||||
|
||||
case OPARAM:
|
||||
@ -1002,7 +1032,7 @@ naddr(Node *n, Addr *a)
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
naddr(n->left, a);
|
||||
naddr(n->left, a, canemitcode);
|
||||
if(a->type >= D_INDIR) {
|
||||
a->type -= D_INDIR;
|
||||
break;
|
||||
@ -1018,24 +1048,28 @@ naddr(Node *n, Addr *a)
|
||||
|
||||
case OLEN:
|
||||
// len of string or slice
|
||||
naddr(n->left, a);
|
||||
naddr(n->left, a, canemitcode);
|
||||
a->offset += Array_nel;
|
||||
if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
|
||||
checkoffset(a, canemitcode);
|
||||
break;
|
||||
|
||||
case OCAP:
|
||||
// cap of string or slice
|
||||
naddr(n->left, a);
|
||||
naddr(n->left, a, canemitcode);
|
||||
a->offset += Array_cap;
|
||||
if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero)
|
||||
checkoffset(a, canemitcode);
|
||||
break;
|
||||
|
||||
// case OADD:
|
||||
// if(n->right->op == OLITERAL) {
|
||||
// v = n->right->vconst;
|
||||
// naddr(n->left, a);
|
||||
// naddr(n->left, a, canemitcode);
|
||||
// } else
|
||||
// if(n->left->op == OLITERAL) {
|
||||
// v = n->left->vconst;
|
||||
// naddr(n->right, a);
|
||||
// naddr(n->right, a, canemitcode);
|
||||
// } else
|
||||
// goto bad;
|
||||
// a->offset += v;
|
||||
@ -1618,7 +1652,6 @@ optoas(int op, Type *t)
|
||||
enum
|
||||
{
|
||||
ODynam = 1<<0,
|
||||
OPtrto = 1<<1,
|
||||
};
|
||||
|
||||
static Node clean[20];
|
||||
@ -1707,7 +1740,7 @@ lit:
|
||||
reg1 = &clean[cleani-2];
|
||||
reg->op = OEMPTY;
|
||||
reg1->op = OEMPTY;
|
||||
naddr(n, a);
|
||||
naddr(n, a, 1);
|
||||
goto yes;
|
||||
|
||||
odot:
|
||||
@ -1720,7 +1753,7 @@ odot:
|
||||
n1 = *nn;
|
||||
n1.type = n->type;
|
||||
n1.xoffset += oary[0];
|
||||
naddr(&n1, a);
|
||||
naddr(&n1, a, 1);
|
||||
goto yes;
|
||||
}
|
||||
|
||||
@ -1744,7 +1777,7 @@ odot:
|
||||
|
||||
a->type = D_NONE;
|
||||
a->index = D_NONE;
|
||||
naddr(&n1, a);
|
||||
naddr(&n1, a, 1);
|
||||
goto yes;
|
||||
|
||||
oindex:
|
||||
@ -1755,18 +1788,12 @@ oindex:
|
||||
|
||||
// set o to type of array
|
||||
o = 0;
|
||||
if(isptr[l->type->etype]) {
|
||||
o += OPtrto;
|
||||
if(l->type->type->etype != TARRAY)
|
||||
fatal("not ptr ary");
|
||||
if(l->type->type->bound < 0)
|
||||
o += ODynam;
|
||||
} else {
|
||||
if(l->type->etype != TARRAY)
|
||||
fatal("not ary");
|
||||
if(l->type->bound < 0)
|
||||
o += ODynam;
|
||||
}
|
||||
if(isptr[l->type->etype])
|
||||
fatal("ptr ary");
|
||||
if(l->type->etype != TARRAY)
|
||||
fatal("not ary");
|
||||
if(l->type->bound < 0)
|
||||
o += ODynam;
|
||||
|
||||
w = n->type->width;
|
||||
if(isconst(r, CTINT))
|
||||
@ -1785,10 +1812,7 @@ oindex:
|
||||
// load the array (reg)
|
||||
if(l->ullman > r->ullman) {
|
||||
regalloc(reg, types[tptr], N);
|
||||
if(o & OPtrto)
|
||||
cgen(l, reg);
|
||||
else
|
||||
agen(l, reg);
|
||||
agen(l, reg);
|
||||
}
|
||||
|
||||
// load the index (reg1)
|
||||
@ -1804,10 +1828,7 @@ oindex:
|
||||
// load the array (reg)
|
||||
if(l->ullman <= r->ullman) {
|
||||
regalloc(reg, types[tptr], N);
|
||||
if(o & OPtrto)
|
||||
cgen(l, reg);
|
||||
else
|
||||
agen(l, reg);
|
||||
agen(l, reg);
|
||||
}
|
||||
|
||||
// check bounds
|
||||
@ -1818,9 +1839,16 @@ oindex:
|
||||
n2.type = types[tptr];
|
||||
n2.xoffset = Array_nel;
|
||||
} else {
|
||||
if(l->type->width >= unmappedzero && l->op == OIND) {
|
||||
// cannot rely on page protections to
|
||||
// catch array ptr == 0, so dereference.
|
||||
n2 = *reg;
|
||||
n2.op = OINDREG;
|
||||
n2.type = types[TUINT8];
|
||||
n2.xoffset = 0;
|
||||
gins(ATESTB, nodintconst(0), &n2);
|
||||
}
|
||||
nodconst(&n2, types[TUINT64], l->type->bound);
|
||||
if(o & OPtrto)
|
||||
nodconst(&n2, types[TUINT64], l->type->type->bound);
|
||||
}
|
||||
gins(optoas(OCMP, types[TUINT32]), reg1, &n2);
|
||||
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
|
||||
@ -1836,7 +1864,7 @@ oindex:
|
||||
gmove(&n2, reg);
|
||||
}
|
||||
|
||||
naddr(reg1, a);
|
||||
naddr(reg1, a, 1);
|
||||
a->offset = 0;
|
||||
a->scale = w;
|
||||
a->index = a->type;
|
||||
@ -1850,10 +1878,7 @@ oindex_const:
|
||||
// can multiply by width statically
|
||||
|
||||
regalloc(reg, types[tptr], N);
|
||||
if(o & OPtrto)
|
||||
cgen(l, reg);
|
||||
else
|
||||
agen(l, reg);
|
||||
agen(l, reg);
|
||||
|
||||
v = mpgetfix(r->val.u.xval);
|
||||
if(o & ODynam) {
|
||||
@ -1881,10 +1906,6 @@ oindex_const:
|
||||
if(v < 0) {
|
||||
yyerror("out of bounds on array");
|
||||
} else
|
||||
if(o & OPtrto) {
|
||||
if(v >= l->type->type->bound)
|
||||
yyerror("out of bounds on array");
|
||||
} else
|
||||
if(v >= l->type->bound) {
|
||||
yyerror("out of bounds on array");
|
||||
}
|
||||
@ -1895,7 +1916,7 @@ oindex_const:
|
||||
n2.xoffset = v*w;
|
||||
a->type = D_NONE;
|
||||
a->index = D_NONE;
|
||||
naddr(&n2, a);
|
||||
naddr(&n2, a, 1);
|
||||
goto yes;
|
||||
|
||||
yes:
|
||||
|
@ -81,7 +81,7 @@ setoutvar(void)
|
||||
while(t != T) {
|
||||
n = nodarg(t, 1);
|
||||
a = zprog.from;
|
||||
naddr(n, &a);
|
||||
naddr(n, &a, 0);
|
||||
bit = mkvar(R, &a);
|
||||
for(z=0; z<BITS; z++)
|
||||
ovar.b[z] |= bit.b[z];
|
||||
|
@ -63,7 +63,7 @@ widstruct(Type *t, uint32 o, int flag)
|
||||
if(f->etype != TFIELD)
|
||||
fatal("widstruct: not TFIELD: %lT", f);
|
||||
dowidth(f->type);
|
||||
if(f->type->width < 0 || f->type->width > 100000000)
|
||||
if(f->type->width < 0)
|
||||
fatal("invalid width %lld", f->type->width);
|
||||
w = f->type->width;
|
||||
m = arrayelemwidth(f->type);
|
||||
@ -239,7 +239,7 @@ dowidth(Type *t)
|
||||
// width of func type is pointer
|
||||
w = widthptr;
|
||||
break;
|
||||
|
||||
|
||||
case TFUNCARGS:
|
||||
// function is 3 cated structures;
|
||||
// compute their widths as side-effect.
|
||||
|
@ -41,12 +41,12 @@ adderr(int line, char *fmt, va_list arg)
|
||||
{
|
||||
Fmt f;
|
||||
Error *p;
|
||||
|
||||
|
||||
fmtstrinit(&f);
|
||||
fmtprint(&f, "%L: ", line);
|
||||
fmtvprint(&f, fmt, arg);
|
||||
fmtprint(&f, "\n");
|
||||
|
||||
|
||||
if(nerr >= merr) {
|
||||
if(merr == 0)
|
||||
merr = 16;
|
||||
@ -71,7 +71,7 @@ static int
|
||||
errcmp(const void *va, const void *vb)
|
||||
{
|
||||
Error *a, *b;
|
||||
|
||||
|
||||
a = (Error*)va;
|
||||
b = (Error*)vb;
|
||||
if(a->lineno != b->lineno)
|
||||
@ -109,11 +109,11 @@ void
|
||||
yyerrorl(int line, char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
|
||||
va_start(arg, fmt);
|
||||
adderr(line, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
|
||||
hcrash();
|
||||
nerrors++;
|
||||
if(nerrors >= 10 && !debug['e'])
|
||||
@ -2394,7 +2394,6 @@ Node*
|
||||
safeval(Node *n, NodeList **init)
|
||||
{
|
||||
Node *l;
|
||||
Node *r;
|
||||
Node *a;
|
||||
|
||||
// is this a local variable or a dot of a local variable?
|
||||
|
@ -100,6 +100,13 @@ runtime·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
||||
void
|
||||
runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
||||
{
|
||||
if(nel > 0 && old == nil) {
|
||||
// crash if old == nil.
|
||||
// could give a better message
|
||||
// but this is consistent with all the in-line checks
|
||||
// that the compiler inserts for other uses.
|
||||
*old = 0;
|
||||
}
|
||||
|
||||
if(hb > nel || lb > hb) {
|
||||
if(debug) {
|
||||
@ -146,6 +153,13 @@ runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, S
|
||||
void
|
||||
runtime·arraytoslice(byte* old, uint32 nel, Slice ret)
|
||||
{
|
||||
if(nel > 0 && old == nil) {
|
||||
// crash if old == nil.
|
||||
// could give a better message
|
||||
// but this is consistent with all the in-line checks
|
||||
// that the compiler inserts for other uses.
|
||||
*old = 0;
|
||||
}
|
||||
|
||||
// new dope to old array
|
||||
ret.len = nel;
|
||||
|
@ -92,6 +92,68 @@ throw: interface conversion
|
||||
|
||||
panic PC=xxx
|
||||
|
||||
== nilptr/
|
||||
|
||||
=========== nilptr/arrayindex.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/arrayindex1.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/arraytoslice.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/arraytoslice1.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/arraytoslice2.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/slicearray.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0xa
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/structfield.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/structfield1.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/structfield2.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
=========== nilptr/structfieldaddr.go
|
||||
SIGSEGV: segmentation violation
|
||||
Faulting address: 0x0
|
||||
pc: xxx
|
||||
|
||||
|
||||
== fixedbugs/
|
||||
|
||||
=========== fixedbugs/bug016.go
|
||||
@ -140,9 +202,5 @@ panic PC=xxx
|
||||
|
||||
== bugs/
|
||||
|
||||
=========== bugs/bug162.go
|
||||
123
|
||||
BUG: should fail
|
||||
|
||||
=========== bugs/bug193.go
|
||||
BUG: errchk: bugs/bug193.go:14: missing expected error: 'shift'
|
||||
|
@ -21,5 +21,5 @@ func main() {
|
||||
// Pointer offsets and array indices, if they are
|
||||
// very large, need to dereference the base pointer
|
||||
// to trigger a trap.
|
||||
println(p[uintptr(unsafe.Pointer(&x))]);
|
||||
println(p[uintptr(unsafe.Pointer(&x))]); // should crash
|
||||
}
|
30
test/nilptr/arrayindex1.go
Normal file
30
test/nilptr/arrayindex1.go
Normal file
@ -0,0 +1,30 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into p[] with a large
|
||||
// enough index jumps out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
// Pointer offsets and array indices, if they are
|
||||
// very large, need to dereference the base pointer
|
||||
// to trigger a trap.
|
||||
var p *[1<<30]byte = nil;
|
||||
println(p[256<<20]); // very likely to be inside dummy, but should crash
|
||||
}
|
35
test/nilptr/arraytoslice.go
Normal file
35
test/nilptr/arraytoslice.go
Normal file
@ -0,0 +1,35 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func f([]byte) {
|
||||
panic("unreachable");
|
||||
}
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into p[] with a large
|
||||
// enough index can jump out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
//
|
||||
// To avoid needing a check on every slice beyond the
|
||||
// usual len and cap, we require the *array -> slice
|
||||
// conversion to do the check.
|
||||
var p *[1<<30]byte = nil;
|
||||
f(p); // should crash
|
||||
}
|
32
test/nilptr/arraytoslice1.go
Normal file
32
test/nilptr/arraytoslice1.go
Normal file
@ -0,0 +1,32 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into p[] with a large
|
||||
// enough index can jump out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
//
|
||||
// To avoid needing a check on every slice beyond the
|
||||
// usual len and cap, we require the *array -> slice
|
||||
// conversion to do the check.
|
||||
var p *[1<<30]byte = nil;
|
||||
var x []byte = p; // should crash
|
||||
_ = x;
|
||||
}
|
33
test/nilptr/arraytoslice2.go
Normal file
33
test/nilptr/arraytoslice2.go
Normal file
@ -0,0 +1,33 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
var q *[1<<30]byte;
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into p[] with a large
|
||||
// enough index can jump out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
//
|
||||
// To avoid needing a check on every slice beyond the
|
||||
// usual len and cap, we require the *array -> slice
|
||||
// conversion to do the check.
|
||||
var x []byte;
|
||||
var y = &x;
|
||||
*y = q; // should crash (uses arraytoslice runtime routine)
|
||||
}
|
31
test/nilptr/slicearray.go
Normal file
31
test/nilptr/slicearray.go
Normal file
@ -0,0 +1,31 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into p[] with a large
|
||||
// enough index can jump out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
//
|
||||
// To avoid needing a check on every slice beyond the
|
||||
// usual len and cap, we require the slice operation
|
||||
// to do the check.
|
||||
var p *[1<<30]byte = nil;
|
||||
var _ []byte = p[10:len(p)-10]; // should crash
|
||||
}
|
33
test/nilptr/structfield.go
Normal file
33
test/nilptr/structfield.go
Normal file
@ -0,0 +1,33 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
type T struct {
|
||||
x [256<<20] byte;
|
||||
i int;
|
||||
}
|
||||
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into t with a large
|
||||
// enough index can jump out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
// We require the pointer dereference to check.
|
||||
var t *T;
|
||||
println(t.i); // should crash
|
||||
}
|
36
test/nilptr/structfield1.go
Normal file
36
test/nilptr/structfield1.go
Normal file
@ -0,0 +1,36 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
type T struct {
|
||||
x [256<<20] byte;
|
||||
i int;
|
||||
}
|
||||
|
||||
func f() *T {
|
||||
return nil;
|
||||
}
|
||||
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into t with a large
|
||||
// enough index can jump out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
// We require the pointer dereference to check.
|
||||
println(f().i); // should crash
|
||||
}
|
35
test/nilptr/structfield2.go
Normal file
35
test/nilptr/structfield2.go
Normal file
@ -0,0 +1,35 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
type T struct {
|
||||
x [256<<20] byte;
|
||||
i int;
|
||||
}
|
||||
|
||||
var y *T;
|
||||
var x = &y;
|
||||
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into t with a large
|
||||
// enough index can jump out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
// We require the pointer dereference to check.
|
||||
println((*x).i); // should crash
|
||||
}
|
33
test/nilptr/structfieldaddr.go
Normal file
33
test/nilptr/structfieldaddr.go
Normal file
@ -0,0 +1,33 @@
|
||||
// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should fail)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var dummy [512<<20]byte; // give us a big address space
|
||||
type T struct {
|
||||
x [256<<20] byte;
|
||||
i int;
|
||||
}
|
||||
|
||||
func main() {
|
||||
// the test only tests what we intend to test
|
||||
// if dummy starts in the first 256 MB of memory.
|
||||
// otherwise there might not be anything mapped
|
||||
// at the address that might be accidentally
|
||||
// dereferenced below.
|
||||
if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
|
||||
panic("dummy too far out");
|
||||
}
|
||||
|
||||
// The problem here is that indexing into t with a large
|
||||
// enough index can jump out of the unmapped section
|
||||
// at the beginning of memory and into valid memory.
|
||||
// We require the address calculation to check.
|
||||
var t *T;
|
||||
println(&t.i); // should crash
|
||||
}
|
Loading…
Reference in New Issue
Block a user