From 72bf3bc1763cd8dd07c511919ca86577720fc163 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 6 Nov 2012 11:35:58 -0800 Subject: [PATCH] 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 --- src/cmd/gc/typecheck.c | 62 ++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index b109d3a1196..35c99c858c1 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -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); + 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); + } } - 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; - } - yyerror("cannot slice %N (type %T)", l, t); - goto error; + goto ret; /* * call and call like