diff options
| author | Keith Randall <khr@golang.org> | 2014-12-19 20:44:18 -0800 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2014-12-22 22:25:48 +0000 |
| commit | fbc56cf05015899aba236d5a68096a770de3ad0a (patch) | |
| tree | 44d489f2452644d208643db8fc19fe566b15a409 /src/cmd | |
| parent | aaa4bf3720bbf69e1ac65414448baf88b5e4cd83 (diff) | |
| download | go-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.c | 30 | ||||
| -rw-r--r-- | src/cmd/ld/dwarf.c | 15 |
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, |
