]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: check for array bounds overflow in slice expression
authorIan Lance Taylor <iant@golang.org>
Tue, 6 Nov 2012 19:35:58 +0000 (11:35 -0800)
committerIan Lance Taylor <iant@golang.org>
Tue, 6 Nov 2012 19:35:58 +0000 (11:35 -0800)
The test for this is test/index.go, which is not run by
default.  That test does not currently pass even after this is
applied, due to issue 4348.

Fixes #4344.

R=golang-dev, daniel.morsing, rsc
CC=golang-dev
https://golang.org/cl/6815085

src/cmd/gc/typecheck.c

index b109d3a119696285afa96f9bf06ed524ee6cea28..35c99c858c17e17fde8454d24686270c1c391d5e 100644 (file)
@@ -905,7 +905,8 @@ reswitch:
                defaultlit(&n->left, T);
                defaultlit(&n->right->left, T);
                defaultlit(&n->right->right, T);
-               if(isfixedarray(n->left->type)) {
+               l = n->left;
+               if(isfixedarray(l->type)) {
                        if(!islvalue(n->left)) {
                                yyerror("invalid operation %N (slice of unaddressable value)", n);
                                goto error;
@@ -913,6 +914,26 @@ reswitch:
                        n->left = nod(OADDR, n->left, N);
                        n->left->implicit = 1;
                        typecheck(&n->left, Erv);
+                       l = n->left;
+               }
+               if((t = l->type) == T)
+                       goto error;
+               tp = nil;
+               if(istype(t, TSTRING)) {
+                       n->type = t;
+                       n->op = OSLICESTR;
+               } else if(isptr[t->etype] && isfixedarray(t->type)) {
+                       tp = t->type;
+                       n->type = typ(TARRAY);
+                       n->type->type = tp->type;
+                       n->type->bound = -1;
+                       dowidth(n->type);
+                       n->op = OSLICEARR;
+               } else if(isslice(t)) {
+                       n->type = t;
+               } else {
+                       yyerror("cannot slice %N (type %T)", l, t);
+                       goto error;
                }
                if(n->right->left != N) {
                        if((t = n->right->left->type) == T)
@@ -921,8 +942,12 @@ reswitch:
                                yyerror("invalid slice index %N (type %T)", n->right->left, t);
                                goto error;
                        }
-                       if(n->right->left->op == OLITERAL && mpgetfix(n->right->left->val.u.xval) < 0)
-                               yyerror("invalid slice index %N (index must be non-negative)", n->right->left);
+                       if(n->right->left->op == OLITERAL) {
+                               if(mpgetfix(n->right->left->val.u.xval) < 0)
+                                       yyerror("invalid slice index %N (index must be non-negative)", n->right->left);
+                               else if(tp != nil && tp->bound > 0 && mpgetfix(n->right->left->val.u.xval) > tp->bound)
+                                       yyerror("invalid slice index %N (out of bounds for %d-element array)", n->right->left, tp->bound);
+                       }
                }
                if(n->right->right != N) {
                        if((t = n->right->right->type) == T)
@@ -931,31 +956,14 @@ reswitch:
                                yyerror("invalid slice index %N (type %T)", n->right->right, t);
                                goto error;
                        }
-                       if(n->right->right->op == OLITERAL && mpgetfix(n->right->right->val.u.xval) < 0)
-                               yyerror("invalid slice index %N (index must be non-negative)", n->right->right);
-               }
-               l = n->left;
-               if((t = l->type) == T)
-                       goto error;
-               if(istype(t, TSTRING)) {
-                       n->type = t;
-                       n->op = OSLICESTR;
-                       goto ret;
-               }
-               if(isptr[t->etype] && isfixedarray(t->type)) {
-                       n->type = typ(TARRAY);
-                       n->type->type = t->type->type;
-                       n->type->bound = -1;
-                       dowidth(n->type);
-                       n->op = OSLICEARR;
-                       goto ret;
-               }
-               if(isslice(t)) {
-                       n->type = t;
-                       goto ret;
+                       if(n->right->right->op == OLITERAL) {
+                               if(mpgetfix(n->right->right->val.u.xval) < 0)
+                                       yyerror("invalid slice index %N (index must be non-negative)", n->right->right);
+                               else if(tp != nil && tp->bound > 0 && mpgetfix(n->right->right->val.u.xval) > tp->bound)
+                                       yyerror("invalid slice index %N (out of bounds for %d-element array)", n->right->right, tp->bound);
+                       }
                }
-               yyerror("cannot slice %N (type %T)", l, t);
-               goto error;
+               goto ret;
 
        /*
         * call and call like