From b89d6309771909674413789100c17c6d96945477 Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Wed, 28 Oct 2009 18:23:53 -0700 Subject: [PATCH] Fix bug when sending via select. selfree maintains a cache of Select structures for several sizes. In newselect, we'll use an entry from the cache if one is found. However, the Scase structures corresponding to a send may have been allocated for the wrong size. In this case we'll write off the end of the Scase into random memory and, generally, read some amount of junk in the receive. This patch fixes the issue by removing the cache, on the advice of rsc. R=rsc CC=go-dev http://go/go-review/1016002 --- src/pkg/runtime/chan.c | 51 ++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c index 04566b41cb..94d906d1e4 100644 --- a/src/pkg/runtime/chan.c +++ b/src/pkg/runtime/chan.c @@ -79,8 +79,6 @@ struct Select Scase* scase[1]; // one per case }; -static Select* selfree[20]; - static SudoG* dequeue(WaitQ*, Hchan*); static void enqueue(WaitQ*, SudoG*); static SudoG* allocsg(Hchan*); @@ -446,16 +444,7 @@ runtime·newselect(int32 size, ...) if(size > 1) n = size-1; - lock(&chanlock); - sel = nil; - if(size >= 1 && size < nelem(selfree)) { - sel = selfree[size]; - if(sel != nil) - selfree[size] = sel->link; - } - unlock(&chanlock); - if(sel == nil) - sel = mal(sizeof(*sel) + n*sizeof(sel->scase[0])); + sel = mal(sizeof(*sel) + n*sizeof(sel->scase[0])); sel->tcase = size; sel->ncase = 0; @@ -485,11 +474,8 @@ runtime·selectsend(Select *sel, Hchan *c, ...) if(i >= sel->tcase) throw("selectsend: too many cases"); sel->ncase = i+1; - cas = sel->scase[i]; - if(cas == nil) { - cas = mal(sizeof *cas + c->elemsize - sizeof(cas->u.elem)); - sel->scase[i] = cas; - } + cas = mal(sizeof *cas + c->elemsize - sizeof(cas->u.elem)); + sel->scase[i] = cas; cas->pc = runtime·getcallerpc(&sel); cas->chan = c; @@ -509,7 +495,7 @@ runtime·selectsend(Select *sel, Hchan *c, ...) runtime·printpointer(cas->pc); prints(" chan="); runtime·printpointer(cas->chan); - prints(" po="); + prints(" so="); runtime·printint(cas->so); prints(" send="); runtime·printint(cas->send); @@ -532,11 +518,8 @@ runtime·selectrecv(Select *sel, Hchan *c, ...) if(i >= sel->tcase) throw("selectrecv: too many cases"); sel->ncase = i+1; - cas = sel->scase[i]; - if(cas == nil) { - cas = mal(sizeof *cas); - sel->scase[i] = cas; - } + cas = mal(sizeof *cas); + sel->scase[i] = cas; cas->pc = runtime·getcallerpc(&sel); cas->chan = c; @@ -573,11 +556,8 @@ runtime·selectdefault(Select *sel, ...) if(i >= sel->tcase) throw("selectdefault: too many cases"); sel->ncase = i+1; - cas = sel->scase[i]; - if(cas == nil) { - cas = mal(sizeof *cas); - sel->scase[i] = cas; - } + cas = mal(sizeof *cas); + sel->scase[i] = cas; cas->pc = runtime·getcallerpc(&sel); cas->chan = nil; @@ -598,6 +578,16 @@ runtime·selectdefault(Select *sel, ...) } } +static void +freesel(Select *sel) +{ + uint32 i; + + for(i=0; incase; i++) + free(sel->scase[i]); + free(sel); +} + // selectgo(sel *byte); void runtime·selectgo(Select *sel) @@ -863,14 +853,11 @@ sclose: goto retc; retc: - if(sel->ncase >= 1 && sel->ncase < nelem(selfree)) { - sel->link = selfree[sel->ncase]; - selfree[sel->ncase] = sel; - } unlock(&chanlock); runtime·setcallerpc(&sel, cas->pc); as = (byte*)&sel + cas->so; + freesel(sel); *as = true; } -- 2.50.0