From: Russ Cox Date: Sun, 16 Feb 2014 01:00:57 +0000 (-0500) Subject: cmd/gc: avoid pointer beyond array in range loop X-Git-Tag: go1.3beta1~684 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=8b6ef69e239ac9abbb187915dbd345c0406435ec;p=gostls13.git cmd/gc: avoid pointer beyond array in range loop This problem was discovered by reading the code. I have not seen it in practice, nor do I have any ideas on how to trigger it reliably in a test. But it's still worth fixing. TBR=ken2 CC=golang-codereviews https://golang.org/cl/64370046 --- diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c index d20734ae07..cfe713c130 100644 --- a/src/cmd/gc/range.c +++ b/src/cmd/gc/range.c @@ -173,13 +173,23 @@ walkrange(Node *n) a->list = list(list1(v1), v2); a->rlist = list(list1(hv1), nod(OIND, hp, N)); body = list1(a); - + + // Advance pointer as part of increment. + // We used to advance the pointer before executing the loop body, + // but doing so would make the pointer point past the end of the + // array during the final iteration, possibly causing another unrelated + // piece of memory not to be garbage collected until the loop finished. + // Advancing during the increment ensures that the pointer p only points + // pass the end of the array during the final "p++; i++; if(i >= len(x)) break;", + // after which p is dead, so it cannot confuse the collector. tmp = nod(OADD, hp, nodintconst(t->type->width)); tmp->type = hp->type; tmp->typecheck = 1; tmp->right->type = types[tptr]; tmp->right->typecheck = 1; - body = list(body, nod(OAS, hp, tmp)); + a = nod(OAS, hp, tmp); + typecheck(&a, Etop); + n->nincr->ninit = list1(a); } break;