]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: avoid pointer beyond array in range loop
authorRuss Cox <rsc@golang.org>
Sun, 16 Feb 2014 01:00:57 +0000 (20:00 -0500)
committerRuss Cox <rsc@golang.org>
Sun, 16 Feb 2014 01:00:57 +0000 (20:00 -0500)
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

index d20734ae0709f6a18b9743f53edb74e482d02260..cfe713c1307fe602778750d43b5dfe2757673184 100644 (file)
@@ -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;