Commit a84abbe5 authored by Russ Cox's avatar Russ Cox

gc: zero-width struct, zero-length array fixes

Fixes #1774.
Fixes #2095.
Fixes #2097.

R=ken2
CC=golang-dev
https://golang.org/cl/4826046
parent dec8009f
...@@ -595,9 +595,6 @@ agen(Node *n, Node *res) ...@@ -595,9 +595,6 @@ agen(Node *n, Node *res)
// i is in &n1 (if not constant) // i is in &n1 (if not constant)
// w is width // w is width
if(w == 0)
fatal("index is zero width");
// constant index // constant index
if(isconst(nr, CTINT)) { if(isconst(nr, CTINT)) {
if(isconst(nl, CTSTR)) if(isconst(nl, CTSTR))
...@@ -683,7 +680,9 @@ agen(Node *n, Node *res) ...@@ -683,7 +680,9 @@ agen(Node *n, Node *res)
gmove(&n1, &n3); 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); memset(&n4, 0, sizeof n4);
n4.op = OADDR; n4.op = OADDR;
n4.left = &n2; n4.left = &n2;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
int thechar = '5'; int thechar = '5';
char* thestring = "arm"; char* thestring = "arm";
vlong MAXWIDTH = (1LL<<32) - 1;
/* /*
* go declares several platform-specific type aliases: * go declares several platform-specific type aliases:
......
...@@ -510,9 +510,6 @@ agen(Node *n, Node *res) ...@@ -510,9 +510,6 @@ agen(Node *n, Node *res)
regfree(&n4); regfree(&n4);
} }
if(w == 0)
fatal("index is zero width");
// constant index // constant index
if(isconst(nr, CTINT)) { if(isconst(nr, CTINT)) {
if(isconst(nl, CTSTR)) if(isconst(nl, CTSTR))
...@@ -600,7 +597,9 @@ agen(Node *n, Node *res) ...@@ -600,7 +597,9 @@ agen(Node *n, Node *res)
gmove(&n1, &n3); 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 = gins(ALEAQ, &n2, &n3);
p1->from.scale = w; p1->from.scale = w;
p1->from.index = p1->from.type; p1->from.index = p1->from.type;
...@@ -608,7 +607,6 @@ agen(Node *n, Node *res) ...@@ -608,7 +607,6 @@ agen(Node *n, Node *res)
} else { } else {
ginscon(optoas(OMUL, t), w, &n2); ginscon(optoas(OMUL, t), w, &n2);
gins(optoas(OADD, types[tptr]), &n2, &n3); gins(optoas(OADD, types[tptr]), &n2, &n3);
gmove(&n3, res);
} }
indexdone: indexdone:
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
int thechar = '6'; int thechar = '6';
char* thestring = "amd64"; char* thestring = "amd64";
vlong MAXWIDTH = 1LL<<50;
/* /*
* go declares several platform-specific type aliases: * go declares several platform-specific type aliases:
......
...@@ -562,9 +562,6 @@ agen(Node *n, Node *res) ...@@ -562,9 +562,6 @@ agen(Node *n, Node *res)
regfree(&n4); regfree(&n4);
} }
if(w == 0)
fatal("index is zero width");
// constant index // constant index
if(isconst(nr, CTINT)) { if(isconst(nr, CTINT)) {
if(isconst(nl, CTSTR)) if(isconst(nl, CTSTR))
...@@ -639,7 +636,9 @@ agen(Node *n, Node *res) ...@@ -639,7 +636,9 @@ agen(Node *n, Node *res)
gmove(&n1, &n3); 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 = gins(ALEAL, &n2, &n3);
p1->from.scale = w; p1->from.scale = w;
p1->from.index = p1->from.type; p1->from.index = p1->from.type;
...@@ -648,7 +647,6 @@ agen(Node *n, Node *res) ...@@ -648,7 +647,6 @@ agen(Node *n, Node *res)
nodconst(&n1, types[TUINT32], w); nodconst(&n1, types[TUINT32], w);
gins(optoas(OMUL, types[TUINT32]), &n1, &n2); gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
gins(optoas(OADD, types[tptr]), &n2, &n3); gins(optoas(OADD, types[tptr]), &n2, &n3);
gmove(&n3, res);
} }
indexdone: indexdone:
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
int thechar = '8'; int thechar = '8';
char* thestring = "386"; char* thestring = "386";
vlong MAXWIDTH = (1LL<<32) - 1;
/* /*
* go declares several platform-specific type aliases: * go declares several platform-specific type aliases:
......
...@@ -30,14 +30,18 @@ offmod(Type *t) ...@@ -30,14 +30,18 @@ offmod(Type *t)
o = 0; o = 0;
for(f=t->type; f!=T; f=f->down) { for(f=t->type; f!=T; f=f->down) {
if(f->etype != TFIELD) if(f->etype != TFIELD)
fatal("widstruct: not TFIELD: %lT", f); fatal("offmod: not TFIELD: %lT", f);
f->width = o; f->width = o;
o += widthptr; o += widthptr;
if(o >= MAXWIDTH) {
yyerror("interface too large");
o = widthptr;
}
} }
} }
static uint32 static vlong
widstruct(Type *t, uint32 o, int flag) widstruct(Type *errtype, Type *t, vlong o, int flag)
{ {
Type *f; Type *f;
int32 w, maxalign; int32 w, maxalign;
...@@ -69,6 +73,10 @@ widstruct(Type *t, uint32 o, int flag) ...@@ -69,6 +73,10 @@ widstruct(Type *t, uint32 o, int flag)
f->nname->xoffset = o; f->nname->xoffset = o;
} }
o += w; o += w;
if(o >= MAXWIDTH) {
yyerror("type %lT too large", errtype);
o = 8; // small but nonzero
}
} }
// final width is rounded // final width is rounded
if(flag) if(flag)
...@@ -226,10 +234,7 @@ dowidth(Type *t) ...@@ -226,10 +234,7 @@ dowidth(Type *t)
dowidth(t->type); dowidth(t->type);
if(t->type->width != 0) { if(t->type->width != 0) {
if(tptr == TPTR32) cap = (MAXWIDTH-1) / t->type->width;
cap = ((uint32)-1) / t->type->width;
else
cap = ((uint64)-1) / t->type->width;
if(t->bound > cap) if(t->bound > cap)
yyerror("type %lT larger than address space", t); yyerror("type %lT larger than address space", t);
} }
...@@ -250,7 +255,7 @@ dowidth(Type *t) ...@@ -250,7 +255,7 @@ dowidth(Type *t)
case TSTRUCT: case TSTRUCT:
if(t->funarg) if(t->funarg)
fatal("dowidth fn struct %T", t); fatal("dowidth fn struct %T", t);
w = widstruct(t, 0, 1); w = widstruct(t, t, 0, 1);
break; break;
case TFUNC: case TFUNC:
...@@ -268,9 +273,9 @@ dowidth(Type *t) ...@@ -268,9 +273,9 @@ dowidth(Type *t)
// function is 3 cated structures; // function is 3 cated structures;
// compute their widths as side-effect. // compute their widths as side-effect.
t1 = t->type; t1 = t->type;
w = widstruct(*getthis(t1), 0, 0); w = widstruct(t->type, *getthis(t1), 0, 0);
w = widstruct(*getinarg(t1), w, widthptr); w = widstruct(t->type, *getinarg(t1), w, widthptr);
w = widstruct(*getoutarg(t1), w, widthptr); w = widstruct(t->type, *getoutarg(t1), w, widthptr);
t1->argwid = w; t1->argwid = w;
if(w%widthptr) if(w%widthptr)
warn("bad type %T %d\n", t1, w); warn("bad type %T %d\n", t1, w);
......
...@@ -43,9 +43,10 @@ enum ...@@ -43,9 +43,10 @@ enum
AMEMWORD, AMEMWORD,
BADWIDTH = -1000000000, BADWIDTH = -1000000000,
MAXWIDTH = 1<<30
}; };
extern vlong MAXWIDTH;
/* /*
* note this is the representation * note this is the representation
* of the compilers string literals, * of the compilers string literals,
......
...@@ -20,7 +20,7 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret) ...@@ -20,7 +20,7 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
{ {
if(len < 0 || (int32)len != len) if(len < 0 || (int32)len != len)
runtime·panicstring("makeslice: len out of range"); 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"); runtime·panicstring("makeslice: cap out of range");
makeslice1(t, len, cap, &ret); makeslice1(t, len, cap, &ret);
......
...@@ -47,15 +47,6 @@ func bigcap() { ...@@ -47,15 +47,6 @@ func bigcap() {
g1 = make([]int, 10, big) g1 = make([]int, 10, big)
} }
const (
addrBits = 8*uint(unsafe.Sizeof((*byte)(nil)))
sh = addrBits/2 - 2
)
var g2 [][1<<sh][1<<sh]byte
func overflow() {
g2 = make([][1<<sh][1<<sh]byte, 64)
}
var g3 map[int]int var g3 map[int]int
func badmapcap() { func badmapcap() {
g3 = make(map[int]int, minus1) g3 = make(map[int]int, minus1)
...@@ -74,6 +65,8 @@ func bigchancap() { ...@@ -74,6 +65,8 @@ func bigchancap() {
g4 = make(chan int, big) g4 = make(chan int, big)
} }
const addrBits = unsafe.Sizeof((*byte)(nil))
var g5 chan [1<<15]byte var g5 chan [1<<15]byte
func overflowchan() { func overflowchan() {
if addrBits == 32 { if addrBits == 32 {
...@@ -92,7 +85,6 @@ func main() { ...@@ -92,7 +85,6 @@ func main() {
shouldfail(badcap, "badcap") shouldfail(badcap, "badcap")
shouldfail(badcap1, "badcap1") shouldfail(badcap1, "badcap1")
shouldfail(bigcap, "bigcap") shouldfail(bigcap, "bigcap")
shouldfail(overflow, "overflow")
shouldfail(badmapcap, "badmapcap") shouldfail(badmapcap, "badmapcap")
shouldfail(bigmapcap, "bigmapcap") shouldfail(bigmapcap, "bigmapcap")
shouldfail(badchancap, "badchancap") shouldfail(badchancap, "badchancap")
......
// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug352
// Copyright 2011 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
var x [10][0]byte
var y = make([]struct{}, 10)
func main() {
if &x[1] != &x[2] {
println("BUG: bug352 [0]byte")
}
if &y[1] != &y[2] {
println("BUG: bug352 struct{}")
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment