mirror of
https://github.com/golang/go
synced 2024-11-25 10:17:57 -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:
|
case ODOTPTR:
|
||||||
cgen(nl, res);
|
cgen(nl, res);
|
||||||
if(n->xoffset != 0) {
|
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);
|
nodconst(&n1, types[TINT64], n->xoffset);
|
||||||
gins(optoas(OADD, types[tptr]), &n1, res);
|
gins(optoas(OADD, types[tptr]), &n1, res);
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ EXTERN Node* deferreturn;
|
|||||||
EXTERN Node* throwindex;
|
EXTERN Node* throwindex;
|
||||||
EXTERN Node* throwslice;
|
EXTERN Node* throwslice;
|
||||||
EXTERN Node* throwreturn;
|
EXTERN Node* throwreturn;
|
||||||
|
EXTERN vlong unmappedzero;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gen.c
|
* gen.c
|
||||||
@ -92,7 +93,7 @@ void sgen(Node*, Node*, int32);
|
|||||||
void gmove(Node*, Node*);
|
void gmove(Node*, Node*);
|
||||||
Prog* gins(int, Node*, Node*);
|
Prog* gins(int, Node*, Node*);
|
||||||
int samaddr(Node*, Node*);
|
int samaddr(Node*, Node*);
|
||||||
void naddr(Node*, Addr*);
|
void naddr(Node*, Addr*, int);
|
||||||
void cgen_aret(Node*, Node*);
|
void cgen_aret(Node*, Node*);
|
||||||
int cgen_inline(Node*, Node*);
|
int cgen_inline(Node*, Node*);
|
||||||
void restx(Node*, Node*);
|
void restx(Node*, Node*);
|
||||||
|
@ -1137,7 +1137,7 @@ cgen_inline(Node *n, Node *res)
|
|||||||
goto no;
|
goto no;
|
||||||
if(!n->left->addable)
|
if(!n->left->addable)
|
||||||
goto no;
|
goto no;
|
||||||
if(strcmp(n->left->sym->package, "sys") != 0)
|
if(strcmp(n->left->sym->package, "runtime") != 0)
|
||||||
goto no;
|
goto no;
|
||||||
if(strcmp(n->left->sym->name, "slicearray") == 0)
|
if(strcmp(n->left->sym->name, "slicearray") == 0)
|
||||||
goto slicearray;
|
goto slicearray;
|
||||||
@ -1215,6 +1215,16 @@ slicearray:
|
|||||||
}
|
}
|
||||||
gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
|
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++) {
|
for(i=0; i<5; i++) {
|
||||||
if(nodes[i].op == OREGISTER)
|
if(nodes[i].op == OREGISTER)
|
||||||
regfree(&nodes[i]);
|
regfree(&nodes[i]);
|
||||||
@ -1241,6 +1251,16 @@ arraytoslice:
|
|||||||
n2.xoffset += Array_array;
|
n2.xoffset += Array_array;
|
||||||
gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
|
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++) {
|
for(i=0; i<2; i++) {
|
||||||
if(nodes[i].op == OREGISTER)
|
if(nodes[i].op == OREGISTER)
|
||||||
regfree(&nodes[i]);
|
regfree(&nodes[i]);
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
|
|
||||||
#include "gg.h"
|
#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
|
void
|
||||||
clearp(Prog *p)
|
clearp(Prog *p)
|
||||||
{
|
{
|
||||||
@ -832,6 +836,7 @@ gins(int as, Node *f, Node *t)
|
|||||||
// Node nod;
|
// Node nod;
|
||||||
// int32 v;
|
// int32 v;
|
||||||
Prog *p;
|
Prog *p;
|
||||||
|
Addr af, at;
|
||||||
|
|
||||||
// if(f != N && f->op == OINDEX) {
|
// if(f != N && f->op == OINDEX) {
|
||||||
// regalloc(&nod, ®node, Z);
|
// regalloc(&nod, ®node, Z);
|
||||||
@ -861,22 +866,46 @@ gins(int as, Node *f, Node *t)
|
|||||||
return nil;
|
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);
|
p = prog(as);
|
||||||
if(f != N)
|
if(f != N)
|
||||||
naddr(f, &p->from);
|
p->from = af;
|
||||||
if(t != N)
|
if(t != N)
|
||||||
naddr(t, &p->to);
|
p->to = at;
|
||||||
if(debug['g'])
|
if(debug['g'])
|
||||||
print("%P\n", p);
|
print("%P\n", p);
|
||||||
return 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;
|
* generate code to compute n;
|
||||||
* make a refer to result.
|
* make a refer to result.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
naddr(Node *n, Addr *a)
|
naddr(Node *n, Addr *a, int canemitcode)
|
||||||
{
|
{
|
||||||
a->scale = 0;
|
a->scale = 0;
|
||||||
a->index = D_NONE;
|
a->index = D_NONE;
|
||||||
@ -920,6 +949,7 @@ naddr(Node *n, Addr *a)
|
|||||||
a->type = n->val.u.reg+D_INDIR;
|
a->type = n->val.u.reg+D_INDIR;
|
||||||
a->sym = n->sym;
|
a->sym = n->sym;
|
||||||
a->offset = n->xoffset;
|
a->offset = n->xoffset;
|
||||||
|
checkoffset(a, canemitcode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPARAM:
|
case OPARAM:
|
||||||
@ -1002,7 +1032,7 @@ naddr(Node *n, Addr *a)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case OADDR:
|
case OADDR:
|
||||||
naddr(n->left, a);
|
naddr(n->left, a, canemitcode);
|
||||||
if(a->type >= D_INDIR) {
|
if(a->type >= D_INDIR) {
|
||||||
a->type -= D_INDIR;
|
a->type -= D_INDIR;
|
||||||
break;
|
break;
|
||||||
@ -1018,24 +1048,28 @@ naddr(Node *n, Addr *a)
|
|||||||
|
|
||||||
case OLEN:
|
case OLEN:
|
||||||
// len of string or slice
|
// len of string or slice
|
||||||
naddr(n->left, a);
|
naddr(n->left, a, canemitcode);
|
||||||
a->offset += Array_nel;
|
a->offset += Array_nel;
|
||||||
|
if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
|
||||||
|
checkoffset(a, canemitcode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OCAP:
|
case OCAP:
|
||||||
// cap of string or slice
|
// cap of string or slice
|
||||||
naddr(n->left, a);
|
naddr(n->left, a, canemitcode);
|
||||||
a->offset += Array_cap;
|
a->offset += Array_cap;
|
||||||
|
if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero)
|
||||||
|
checkoffset(a, canemitcode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case OADD:
|
// case OADD:
|
||||||
// if(n->right->op == OLITERAL) {
|
// if(n->right->op == OLITERAL) {
|
||||||
// v = n->right->vconst;
|
// v = n->right->vconst;
|
||||||
// naddr(n->left, a);
|
// naddr(n->left, a, canemitcode);
|
||||||
// } else
|
// } else
|
||||||
// if(n->left->op == OLITERAL) {
|
// if(n->left->op == OLITERAL) {
|
||||||
// v = n->left->vconst;
|
// v = n->left->vconst;
|
||||||
// naddr(n->right, a);
|
// naddr(n->right, a, canemitcode);
|
||||||
// } else
|
// } else
|
||||||
// goto bad;
|
// goto bad;
|
||||||
// a->offset += v;
|
// a->offset += v;
|
||||||
@ -1618,7 +1652,6 @@ optoas(int op, Type *t)
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ODynam = 1<<0,
|
ODynam = 1<<0,
|
||||||
OPtrto = 1<<1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static Node clean[20];
|
static Node clean[20];
|
||||||
@ -1707,7 +1740,7 @@ lit:
|
|||||||
reg1 = &clean[cleani-2];
|
reg1 = &clean[cleani-2];
|
||||||
reg->op = OEMPTY;
|
reg->op = OEMPTY;
|
||||||
reg1->op = OEMPTY;
|
reg1->op = OEMPTY;
|
||||||
naddr(n, a);
|
naddr(n, a, 1);
|
||||||
goto yes;
|
goto yes;
|
||||||
|
|
||||||
odot:
|
odot:
|
||||||
@ -1720,7 +1753,7 @@ odot:
|
|||||||
n1 = *nn;
|
n1 = *nn;
|
||||||
n1.type = n->type;
|
n1.type = n->type;
|
||||||
n1.xoffset += oary[0];
|
n1.xoffset += oary[0];
|
||||||
naddr(&n1, a);
|
naddr(&n1, a, 1);
|
||||||
goto yes;
|
goto yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1744,7 +1777,7 @@ odot:
|
|||||||
|
|
||||||
a->type = D_NONE;
|
a->type = D_NONE;
|
||||||
a->index = D_NONE;
|
a->index = D_NONE;
|
||||||
naddr(&n1, a);
|
naddr(&n1, a, 1);
|
||||||
goto yes;
|
goto yes;
|
||||||
|
|
||||||
oindex:
|
oindex:
|
||||||
@ -1755,18 +1788,12 @@ oindex:
|
|||||||
|
|
||||||
// set o to type of array
|
// set o to type of array
|
||||||
o = 0;
|
o = 0;
|
||||||
if(isptr[l->type->etype]) {
|
if(isptr[l->type->etype])
|
||||||
o += OPtrto;
|
fatal("ptr ary");
|
||||||
if(l->type->type->etype != TARRAY)
|
if(l->type->etype != TARRAY)
|
||||||
fatal("not ptr ary");
|
fatal("not ary");
|
||||||
if(l->type->type->bound < 0)
|
if(l->type->bound < 0)
|
||||||
o += ODynam;
|
o += ODynam;
|
||||||
} else {
|
|
||||||
if(l->type->etype != TARRAY)
|
|
||||||
fatal("not ary");
|
|
||||||
if(l->type->bound < 0)
|
|
||||||
o += ODynam;
|
|
||||||
}
|
|
||||||
|
|
||||||
w = n->type->width;
|
w = n->type->width;
|
||||||
if(isconst(r, CTINT))
|
if(isconst(r, CTINT))
|
||||||
@ -1785,10 +1812,7 @@ oindex:
|
|||||||
// load the array (reg)
|
// load the array (reg)
|
||||||
if(l->ullman > r->ullman) {
|
if(l->ullman > r->ullman) {
|
||||||
regalloc(reg, types[tptr], N);
|
regalloc(reg, types[tptr], N);
|
||||||
if(o & OPtrto)
|
agen(l, reg);
|
||||||
cgen(l, reg);
|
|
||||||
else
|
|
||||||
agen(l, reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the index (reg1)
|
// load the index (reg1)
|
||||||
@ -1804,10 +1828,7 @@ oindex:
|
|||||||
// load the array (reg)
|
// load the array (reg)
|
||||||
if(l->ullman <= r->ullman) {
|
if(l->ullman <= r->ullman) {
|
||||||
regalloc(reg, types[tptr], N);
|
regalloc(reg, types[tptr], N);
|
||||||
if(o & OPtrto)
|
agen(l, reg);
|
||||||
cgen(l, reg);
|
|
||||||
else
|
|
||||||
agen(l, reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check bounds
|
// check bounds
|
||||||
@ -1818,9 +1839,16 @@ oindex:
|
|||||||
n2.type = types[tptr];
|
n2.type = types[tptr];
|
||||||
n2.xoffset = Array_nel;
|
n2.xoffset = Array_nel;
|
||||||
} else {
|
} 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);
|
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);
|
gins(optoas(OCMP, types[TUINT32]), reg1, &n2);
|
||||||
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
|
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
|
||||||
@ -1836,7 +1864,7 @@ oindex:
|
|||||||
gmove(&n2, reg);
|
gmove(&n2, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
naddr(reg1, a);
|
naddr(reg1, a, 1);
|
||||||
a->offset = 0;
|
a->offset = 0;
|
||||||
a->scale = w;
|
a->scale = w;
|
||||||
a->index = a->type;
|
a->index = a->type;
|
||||||
@ -1850,10 +1878,7 @@ oindex_const:
|
|||||||
// can multiply by width statically
|
// can multiply by width statically
|
||||||
|
|
||||||
regalloc(reg, types[tptr], N);
|
regalloc(reg, types[tptr], N);
|
||||||
if(o & OPtrto)
|
agen(l, reg);
|
||||||
cgen(l, reg);
|
|
||||||
else
|
|
||||||
agen(l, reg);
|
|
||||||
|
|
||||||
v = mpgetfix(r->val.u.xval);
|
v = mpgetfix(r->val.u.xval);
|
||||||
if(o & ODynam) {
|
if(o & ODynam) {
|
||||||
@ -1881,10 +1906,6 @@ oindex_const:
|
|||||||
if(v < 0) {
|
if(v < 0) {
|
||||||
yyerror("out of bounds on array");
|
yyerror("out of bounds on array");
|
||||||
} else
|
} else
|
||||||
if(o & OPtrto) {
|
|
||||||
if(v >= l->type->type->bound)
|
|
||||||
yyerror("out of bounds on array");
|
|
||||||
} else
|
|
||||||
if(v >= l->type->bound) {
|
if(v >= l->type->bound) {
|
||||||
yyerror("out of bounds on array");
|
yyerror("out of bounds on array");
|
||||||
}
|
}
|
||||||
@ -1895,7 +1916,7 @@ oindex_const:
|
|||||||
n2.xoffset = v*w;
|
n2.xoffset = v*w;
|
||||||
a->type = D_NONE;
|
a->type = D_NONE;
|
||||||
a->index = D_NONE;
|
a->index = D_NONE;
|
||||||
naddr(&n2, a);
|
naddr(&n2, a, 1);
|
||||||
goto yes;
|
goto yes;
|
||||||
|
|
||||||
yes:
|
yes:
|
||||||
|
@ -81,7 +81,7 @@ setoutvar(void)
|
|||||||
while(t != T) {
|
while(t != T) {
|
||||||
n = nodarg(t, 1);
|
n = nodarg(t, 1);
|
||||||
a = zprog.from;
|
a = zprog.from;
|
||||||
naddr(n, &a);
|
naddr(n, &a, 0);
|
||||||
bit = mkvar(R, &a);
|
bit = mkvar(R, &a);
|
||||||
for(z=0; z<BITS; z++)
|
for(z=0; z<BITS; z++)
|
||||||
ovar.b[z] |= bit.b[z];
|
ovar.b[z] |= bit.b[z];
|
||||||
|
@ -63,7 +63,7 @@ widstruct(Type *t, uint32 o, int flag)
|
|||||||
if(f->etype != TFIELD)
|
if(f->etype != TFIELD)
|
||||||
fatal("widstruct: not TFIELD: %lT", f);
|
fatal("widstruct: not TFIELD: %lT", f);
|
||||||
dowidth(f->type);
|
dowidth(f->type);
|
||||||
if(f->type->width < 0 || f->type->width > 100000000)
|
if(f->type->width < 0)
|
||||||
fatal("invalid width %lld", f->type->width);
|
fatal("invalid width %lld", f->type->width);
|
||||||
w = f->type->width;
|
w = f->type->width;
|
||||||
m = arrayelemwidth(f->type);
|
m = arrayelemwidth(f->type);
|
||||||
@ -239,7 +239,7 @@ dowidth(Type *t)
|
|||||||
// width of func type is pointer
|
// width of func type is pointer
|
||||||
w = widthptr;
|
w = widthptr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TFUNCARGS:
|
case TFUNCARGS:
|
||||||
// function is 3 cated structures;
|
// function is 3 cated structures;
|
||||||
// compute their widths as side-effect.
|
// compute their widths as side-effect.
|
||||||
|
@ -41,12 +41,12 @@ adderr(int line, char *fmt, va_list arg)
|
|||||||
{
|
{
|
||||||
Fmt f;
|
Fmt f;
|
||||||
Error *p;
|
Error *p;
|
||||||
|
|
||||||
fmtstrinit(&f);
|
fmtstrinit(&f);
|
||||||
fmtprint(&f, "%L: ", line);
|
fmtprint(&f, "%L: ", line);
|
||||||
fmtvprint(&f, fmt, arg);
|
fmtvprint(&f, fmt, arg);
|
||||||
fmtprint(&f, "\n");
|
fmtprint(&f, "\n");
|
||||||
|
|
||||||
if(nerr >= merr) {
|
if(nerr >= merr) {
|
||||||
if(merr == 0)
|
if(merr == 0)
|
||||||
merr = 16;
|
merr = 16;
|
||||||
@ -71,7 +71,7 @@ static int
|
|||||||
errcmp(const void *va, const void *vb)
|
errcmp(const void *va, const void *vb)
|
||||||
{
|
{
|
||||||
Error *a, *b;
|
Error *a, *b;
|
||||||
|
|
||||||
a = (Error*)va;
|
a = (Error*)va;
|
||||||
b = (Error*)vb;
|
b = (Error*)vb;
|
||||||
if(a->lineno != b->lineno)
|
if(a->lineno != b->lineno)
|
||||||
@ -109,11 +109,11 @@ void
|
|||||||
yyerrorl(int line, char *fmt, ...)
|
yyerrorl(int line, char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list arg;
|
va_list arg;
|
||||||
|
|
||||||
va_start(arg, fmt);
|
va_start(arg, fmt);
|
||||||
adderr(line, fmt, arg);
|
adderr(line, fmt, arg);
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
|
|
||||||
hcrash();
|
hcrash();
|
||||||
nerrors++;
|
nerrors++;
|
||||||
if(nerrors >= 10 && !debug['e'])
|
if(nerrors >= 10 && !debug['e'])
|
||||||
@ -2394,7 +2394,6 @@ Node*
|
|||||||
safeval(Node *n, NodeList **init)
|
safeval(Node *n, NodeList **init)
|
||||||
{
|
{
|
||||||
Node *l;
|
Node *l;
|
||||||
Node *r;
|
|
||||||
Node *a;
|
Node *a;
|
||||||
|
|
||||||
// is this a local variable or a dot of a local variable?
|
// 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
|
void
|
||||||
runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
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(hb > nel || lb > hb) {
|
||||||
if(debug) {
|
if(debug) {
|
||||||
@ -146,6 +153,13 @@ runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, S
|
|||||||
void
|
void
|
||||||
runtime·arraytoslice(byte* old, uint32 nel, Slice ret)
|
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
|
// new dope to old array
|
||||||
ret.len = nel;
|
ret.len = nel;
|
||||||
|
@ -92,6 +92,68 @@ throw: interface conversion
|
|||||||
|
|
||||||
panic PC=xxx
|
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/
|
||||||
|
|
||||||
=========== fixedbugs/bug016.go
|
=========== fixedbugs/bug016.go
|
||||||
@ -140,9 +202,5 @@ panic PC=xxx
|
|||||||
|
|
||||||
== bugs/
|
== bugs/
|
||||||
|
|
||||||
=========== bugs/bug162.go
|
|
||||||
123
|
|
||||||
BUG: should fail
|
|
||||||
|
|
||||||
=========== bugs/bug193.go
|
=========== bugs/bug193.go
|
||||||
BUG: errchk: bugs/bug193.go:14: missing expected error: 'shift'
|
BUG: errchk: bugs/bug193.go:14: missing expected error: 'shift'
|
||||||
|
@ -21,5 +21,5 @@ func main() {
|
|||||||
// Pointer offsets and array indices, if they are
|
// Pointer offsets and array indices, if they are
|
||||||
// very large, need to dereference the base pointer
|
// very large, need to dereference the base pointer
|
||||||
// to trigger a trap.
|
// 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