Commit 72bf3bc1 authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/gc: check for array bounds overflow in slice expression

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
parent 0ead18c5
...@@ -905,7 +905,8 @@ reswitch: ...@@ -905,7 +905,8 @@ reswitch:
defaultlit(&n->left, T); defaultlit(&n->left, T);
defaultlit(&n->right->left, T); defaultlit(&n->right->left, T);
defaultlit(&n->right->right, T); defaultlit(&n->right->right, T);
if(isfixedarray(n->left->type)) { l = n->left;
if(isfixedarray(l->type)) {
if(!islvalue(n->left)) { if(!islvalue(n->left)) {
yyerror("invalid operation %N (slice of unaddressable value)", n); yyerror("invalid operation %N (slice of unaddressable value)", n);
goto error; goto error;
...@@ -913,6 +914,26 @@ reswitch: ...@@ -913,6 +914,26 @@ reswitch:
n->left = nod(OADDR, n->left, N); n->left = nod(OADDR, n->left, N);
n->left->implicit = 1; n->left->implicit = 1;
typecheck(&n->left, Erv); 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(n->right->left != N) {
if((t = n->right->left->type) == T) if((t = n->right->left->type) == T)
...@@ -921,8 +942,12 @@ reswitch: ...@@ -921,8 +942,12 @@ reswitch:
yyerror("invalid slice index %N (type %T)", n->right->left, t); yyerror("invalid slice index %N (type %T)", n->right->left, t);
goto error; goto error;
} }
if(n->right->left->op == OLITERAL && mpgetfix(n->right->left->val.u.xval) < 0) if(n->right->left->op == OLITERAL) {
yyerror("invalid slice index %N (index must be non-negative)", n->right->left); 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(n->right->right != N) {
if((t = n->right->right->type) == T) if((t = n->right->right->type) == T)
...@@ -931,31 +956,14 @@ reswitch: ...@@ -931,31 +956,14 @@ reswitch:
yyerror("invalid slice index %N (type %T)", n->right->right, t); yyerror("invalid slice index %N (type %T)", n->right->right, t);
goto error; goto error;
} }
if(n->right->right->op == OLITERAL && mpgetfix(n->right->right->val.u.xval) < 0) if(n->right->right->op == OLITERAL) {
yyerror("invalid slice index %N (index must be non-negative)", n->right->right); if(mpgetfix(n->right->right->val.u.xval) < 0)
} yyerror("invalid slice index %N (index must be non-negative)", n->right->right);
l = n->left; else if(tp != nil && tp->bound > 0 && mpgetfix(n->right->right->val.u.xval) > tp->bound)
if((t = l->type) == T) yyerror("invalid slice index %N (out of bounds for %d-element array)", n->right->right, tp->bound);
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;
} }
yyerror("cannot slice %N (type %T)", l, t); goto ret;
goto error;
/* /*
* call and call like * call and call like
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment