aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2014-12-19 20:44:18 -0800
committerKeith Randall <khr@golang.org>2014-12-22 22:25:48 +0000
commitfbc56cf05015899aba236d5a68096a770de3ad0a (patch)
tree44d489f2452644d208643db8fc19fe566b15a409 /src/cmd
parentaaa4bf3720bbf69e1ac65414448baf88b5e4cd83 (diff)
downloadgo-fbc56cf05015899aba236d5a68096a770de3ad0a.tar.xz
runtime: hashmap: move overflow pointer to end of bucket
Pointers to zero-sized values may end up pointing to the next object in memory, and possibly off the end of a span. This can cause memory leaks and/or confuse the garbage collector. By putting the overflow pointer at the end of the bucket, we make sure that pointers to any zero-sized keys or values don't accidentally point to the next object in memory. fixes #9384 Change-Id: I5d434df176984cb0210b4d0195dd106d6eb28f73 Reviewed-on: https://go-review.googlesource.com/1869 Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/gc/reflect.c30
-rw-r--r--src/cmd/ld/dwarf.c15
2 files changed, 26 insertions, 19 deletions
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 897fdc635a..7b17072e59 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -143,18 +143,6 @@ mapbucket(Type *t)
// We don't need to encode it as GC doesn't care about it.
offset = BUCKETSIZE * 1;
- overflowfield = typ(TFIELD);
- overflowfield->type = ptrto(bucket);
- overflowfield->width = offset; // "width" is offset in structure
- overflowfield->sym = mal(sizeof(Sym)); // not important but needs to be set to give this type a name
- overflowfield->sym->name = "overflow";
- offset += widthptr;
-
- // The keys are padded to the native integer alignment.
- // This is usually the same as widthptr; the exception (as usual) is nacl/amd64.
- if(widthreg > widthptr)
- offset += widthreg - widthptr;
-
keysfield = typ(TFIELD);
keysfield->type = typ(TARRAY);
keysfield->type->type = keytype;
@@ -175,11 +163,23 @@ mapbucket(Type *t)
valuesfield->sym->name = "values";
offset += BUCKETSIZE * valtype->width;
+ overflowfield = typ(TFIELD);
+ overflowfield->type = ptrto(bucket);
+ overflowfield->width = offset; // "width" is offset in structure
+ overflowfield->sym = mal(sizeof(Sym)); // not important but needs to be set to give this type a name
+ overflowfield->sym->name = "overflow";
+ offset += widthptr;
+
+ // Pad to the native integer alignment.
+ // This is usually the same as widthptr; the exception (as usual) is nacl/amd64.
+ if(widthreg > widthptr)
+ offset += widthreg - widthptr;
+
// link up fields
- bucket->type = overflowfield;
- overflowfield->down = keysfield;
+ bucket->type = keysfield;
keysfield->down = valuesfield;
- valuesfield->down = T;
+ valuesfield->down = overflowfield;
+ overflowfield->down = T;
bucket->width = offset;
bucket->local = t->local;
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index fbb5699bdb..b5331e829f 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -1281,12 +1281,19 @@ synthesizemaptypes(DWDie *die)
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys");
newrefattr(fld, DW_AT_type, dwhk);
- newmemberoffsetattr(fld, BucketSize + PtrSize);
+ newmemberoffsetattr(fld, BucketSize);
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values");
newrefattr(fld, DW_AT_type, dwhv);
- newmemberoffsetattr(fld, BucketSize + PtrSize + BucketSize * keysize);
- newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize + PtrSize + BucketSize * keysize + BucketSize * valsize, 0);
- substitutetype(dwhb, "overflow", defptrto(dwhb));
+ newmemberoffsetattr(fld, BucketSize + BucketSize * keysize);
+ fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "overflow");
+ newrefattr(fld, DW_AT_type, defptrto(dwhb));
+ newmemberoffsetattr(fld, BucketSize + BucketSize * (keysize + valsize));
+ if(RegSize > PtrSize) {
+ fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "pad");
+ newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
+ newmemberoffsetattr(fld, BucketSize + BucketSize * (keysize + valsize) + PtrSize);
+ }
+ newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize + BucketSize * keysize + BucketSize * valsize + RegSize, 0);
// Construct hash<K,V>
dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,