From 8b6ef69e239ac9abbb187915dbd345c0406435ec Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 15 Feb 2014 20:00:57 -0500 Subject: [PATCH] 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 --- src/cmd/gc/range.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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; -- 2.48.1