From a84abbe5086e8a9d280f3f5bd94f3b7940a00eff Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 27 Jul 2011 16:47:45 -0400 Subject: [PATCH] gc: zero-width struct, zero-length array fixes Fixes #1774. Fixes #2095. Fixes #2097. R=ken2 CC=golang-dev https://golang.org/cl/4826046 --- src/cmd/5g/cgen.c | 7 +++---- src/cmd/5g/galign.c | 1 + src/cmd/6g/cgen.c | 8 +++----- src/cmd/6g/galign.c | 1 + src/cmd/8g/cgen.c | 8 +++----- src/cmd/8g/galign.c | 1 + src/cmd/gc/align.c | 27 ++++++++++++++++----------- src/cmd/gc/go.h | 3 ++- src/pkg/runtime/slice.c | 2 +- test/fixedbugs/bug273.go | 12 ++---------- test/fixedbugs/bug352.go | 19 +++++++++++++++++++ 11 files changed, 52 insertions(+), 37 deletions(-) create mode 100644 test/fixedbugs/bug352.go diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index 76e2707fa9..6e2fbe20ff 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -595,9 +595,6 @@ agen(Node *n, Node *res) // i is in &n1 (if not constant) // w is width - if(w == 0) - fatal("index is zero width"); - // constant index if(isconst(nr, CTINT)) { if(isconst(nl, CTSTR)) @@ -683,7 +680,9 @@ agen(Node *n, Node *res) gmove(&n1, &n3); } - if(w == 1 || w == 2 || w == 4 || w == 8) { + if(w == 0) { + // nothing to do + } else if(w == 1 || w == 2 || w == 4 || w == 8) { memset(&n4, 0, sizeof n4); n4.op = OADDR; n4.left = &n2; diff --git a/src/cmd/5g/galign.c b/src/cmd/5g/galign.c index 0fece9a08f..12766102f1 100644 --- a/src/cmd/5g/galign.c +++ b/src/cmd/5g/galign.c @@ -7,6 +7,7 @@ int thechar = '5'; char* thestring = "arm"; +vlong MAXWIDTH = (1LL<<32) - 1; /* * go declares several platform-specific type aliases: diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index fca4b64dd1..24f88a416e 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -510,9 +510,6 @@ agen(Node *n, Node *res) regfree(&n4); } - if(w == 0) - fatal("index is zero width"); - // constant index if(isconst(nr, CTINT)) { if(isconst(nl, CTSTR)) @@ -600,7 +597,9 @@ agen(Node *n, Node *res) gmove(&n1, &n3); } - if(w == 1 || w == 2 || w == 4 || w == 8) { + if(w == 0) { + // nothing to do + } else if(w == 1 || w == 2 || w == 4 || w == 8) { p1 = gins(ALEAQ, &n2, &n3); p1->from.scale = w; p1->from.index = p1->from.type; @@ -608,7 +607,6 @@ agen(Node *n, Node *res) } else { ginscon(optoas(OMUL, t), w, &n2); gins(optoas(OADD, types[tptr]), &n2, &n3); - gmove(&n3, res); } indexdone: diff --git a/src/cmd/6g/galign.c b/src/cmd/6g/galign.c index 97bfb58e88..e366362b30 100644 --- a/src/cmd/6g/galign.c +++ b/src/cmd/6g/galign.c @@ -7,6 +7,7 @@ int thechar = '6'; char* thestring = "amd64"; +vlong MAXWIDTH = 1LL<<50; /* * go declares several platform-specific type aliases: diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index 1614a2d775..b316e6e345 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -562,9 +562,6 @@ agen(Node *n, Node *res) regfree(&n4); } - if(w == 0) - fatal("index is zero width"); - // constant index if(isconst(nr, CTINT)) { if(isconst(nl, CTSTR)) @@ -639,7 +636,9 @@ agen(Node *n, Node *res) gmove(&n1, &n3); } - if(w == 1 || w == 2 || w == 4 || w == 8) { + if(w == 0) { + // nothing to do + } else if(w == 1 || w == 2 || w == 4 || w == 8) { p1 = gins(ALEAL, &n2, &n3); p1->from.scale = w; p1->from.index = p1->from.type; @@ -648,7 +647,6 @@ agen(Node *n, Node *res) nodconst(&n1, types[TUINT32], w); gins(optoas(OMUL, types[TUINT32]), &n1, &n2); gins(optoas(OADD, types[tptr]), &n2, &n3); - gmove(&n3, res); } indexdone: diff --git a/src/cmd/8g/galign.c b/src/cmd/8g/galign.c index 48edfdf3cc..7734603c4b 100644 --- a/src/cmd/8g/galign.c +++ b/src/cmd/8g/galign.c @@ -7,6 +7,7 @@ int thechar = '8'; char* thestring = "386"; +vlong MAXWIDTH = (1LL<<32) - 1; /* * go declares several platform-specific type aliases: diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c index 6bb93ef179..14c1c4a8d2 100644 --- a/src/cmd/gc/align.c +++ b/src/cmd/gc/align.c @@ -30,14 +30,18 @@ offmod(Type *t) o = 0; for(f=t->type; f!=T; f=f->down) { if(f->etype != TFIELD) - fatal("widstruct: not TFIELD: %lT", f); + fatal("offmod: not TFIELD: %lT", f); f->width = o; o += widthptr; + if(o >= MAXWIDTH) { + yyerror("interface too large"); + o = widthptr; + } } } -static uint32 -widstruct(Type *t, uint32 o, int flag) +static vlong +widstruct(Type *errtype, Type *t, vlong o, int flag) { Type *f; int32 w, maxalign; @@ -69,6 +73,10 @@ widstruct(Type *t, uint32 o, int flag) f->nname->xoffset = o; } o += w; + if(o >= MAXWIDTH) { + yyerror("type %lT too large", errtype); + o = 8; // small but nonzero + } } // final width is rounded if(flag) @@ -226,10 +234,7 @@ dowidth(Type *t) dowidth(t->type); if(t->type->width != 0) { - if(tptr == TPTR32) - cap = ((uint32)-1) / t->type->width; - else - cap = ((uint64)-1) / t->type->width; + cap = (MAXWIDTH-1) / t->type->width; if(t->bound > cap) yyerror("type %lT larger than address space", t); } @@ -250,7 +255,7 @@ dowidth(Type *t) case TSTRUCT: if(t->funarg) fatal("dowidth fn struct %T", t); - w = widstruct(t, 0, 1); + w = widstruct(t, t, 0, 1); break; case TFUNC: @@ -268,9 +273,9 @@ dowidth(Type *t) // function is 3 cated structures; // compute their widths as side-effect. t1 = t->type; - w = widstruct(*getthis(t1), 0, 0); - w = widstruct(*getinarg(t1), w, widthptr); - w = widstruct(*getoutarg(t1), w, widthptr); + w = widstruct(t->type, *getthis(t1), 0, 0); + w = widstruct(t->type, *getinarg(t1), w, widthptr); + w = widstruct(t->type, *getoutarg(t1), w, widthptr); t1->argwid = w; if(w%widthptr) warn("bad type %T %d\n", t1, w); diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index dfc5887a5c..604a1261b8 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -43,9 +43,10 @@ enum AMEMWORD, BADWIDTH = -1000000000, - MAXWIDTH = 1<<30 }; +extern vlong MAXWIDTH; + /* * note this is the representation * of the compilers string literals, diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c index 9146c177f2..70534279b5 100644 --- a/src/pkg/runtime/slice.c +++ b/src/pkg/runtime/slice.c @@ -20,7 +20,7 @@ runtimeĀ·makeslice(SliceType *t, int64 len, int64 cap, Slice ret) { if(len < 0 || (int32)len != len) runtimeĀ·panicstring("makeslice: len out of range"); - if(cap < len || (int32)cap != cap || cap > ((uintptr)-1) / t->elem->size) + if(cap < len || (int32)cap != cap || t->elem->size > 0 && cap > ((uintptr)-1) / t->elem->size) runtimeĀ·panicstring("makeslice: cap out of range"); makeslice1(t, len, cap, &ret); diff --git a/test/fixedbugs/bug273.go b/test/fixedbugs/bug273.go index 816f69e8f1..dd5aaa7b8a 100644 --- a/test/fixedbugs/bug273.go +++ b/test/fixedbugs/bug273.go @@ -47,15 +47,6 @@ func bigcap() { g1 = make([]int, 10, big) } -const ( - addrBits = 8*uint(unsafe.Sizeof((*byte)(nil))) - sh = addrBits/2 - 2 -) -var g2 [][1<