]> Cypherpunks.ru repositories - gostls13.git/commitdiff
gc: index bounds tests and fixes
authorRuss Cox <rsc@golang.org>
Tue, 3 Aug 2010 07:26:02 +0000 (00:26 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 3 Aug 2010 07:26:02 +0000 (00:26 -0700)
move constant index checking to front end
x[2:1] is a compile-time error now too

R=ken2
CC=golang-dev
https://golang.org/cl/1848056

17 files changed:
src/cmd/5g/cgen.c
src/cmd/5g/ggen.c
src/cmd/5g/gsubr.c
src/cmd/6g/cgen.c
src/cmd/6g/ggen.c
src/cmd/6g/gsubr.c
src/cmd/8g/cgen.c
src/cmd/8g/ggen.c
src/cmd/gc/builtin.c.boot
src/cmd/gc/const.c
src/cmd/gc/mparith2.c
src/cmd/gc/runtime.go
src/cmd/gc/typecheck.c
src/cmd/gc/walk.c
src/pkg/runtime/slice.c
test/index.go [new file with mode: 0644]
test/recover2.go

index c3042b1822bde970804135603d2eb5497fc822e0..b0c9b88da455edc7c874ba09f6b9d2ecc37e894b 100644 (file)
@@ -605,13 +605,6 @@ agen(Node *n, Node *res)
                                n1.type = types[tptr];
                                n1.xoffset = Array_array;
                                gmove(&n1, &n3);
-                       } else
-                       if(!debug['B'] && !n->etype) {
-                               if(v < 0)
-                                       yyerror("out of bounds on array");
-                               else
-                               if(v >= nl->type->bound)
-                                       yyerror("out of bounds on array");
                        }
 
                        nodconst(&n2, types[tptr], v*w);
index 2776ac7681e99db641be935a64266311549d0b05..0d87895240eb7141eb7ecfa063700c90d591794a 100644 (file)
@@ -682,6 +682,29 @@ regcmp(const void *va, const void *vb)
 
 static Prog*   throwpc;
 
+// We're only going to bother inlining if we can
+// convert all the arguments to 32 bits safely.  Can we?
+static int
+fix64(NodeList *nn, int n)
+{
+       NodeList *l;
+       Node *r;
+       int i;
+       
+       l = nn;
+       for(i=0; i<n; i++) {
+               r = l->n->right;
+               if(is64(r->type) && !smallintconst(r)) {
+                       if(r->op == OCONV)
+                               r = r->left;
+                       if(is64(r->type))
+                               return 0;
+               }
+               l = l->next;
+       }
+       return 1;
+}
+
 void
 getargs(NodeList *nn, Node *reg, int n)
 {
@@ -813,6 +836,8 @@ cgen_inline(Node *n, Node *res)
 slicearray:
        if(!sleasy(res))
                goto no;
+       if(!fix64(n->list, 5))
+               goto no;
        getargs(n->list, nodes, 5);
 
        // if(hb[3] > nel[1]) goto throw
@@ -904,6 +929,8 @@ slicearray:
        return 1;
 
 sliceslice:
+       if(!fix64(n->list, narg))
+               goto no;
        ntemp.op = OXXX;
        if(!sleasy(n->list->n->right)) {
                Node *n0;
index 741dbe5956d34c0c1c403330ac1eb22223f1cebb..70ebad6edd075f88b2d1e9dcd5432776da862f6d 100644 (file)
@@ -1841,19 +1841,6 @@ oindex_const:
                n1.type = types[tptr];
                n1.xoffset = Array_array;
                gmove(&n1, reg);
-
-       } else
-       if(!debug['B']) {
-               if(v < 0) {
-                       yyerror("out of bounds on array");
-               } else
-               if(o & OPtrto) {
-                       if(v >= l->type->type->bound)
-                               yyerror("out of bounds on array");
-               } else
-               if(v >= l->type->bound) {
-                       yyerror("out of bounds on array");
-               }
        }
 
        n2 = *reg;
index aacc0d06f0d78bf8bba5f74233305f737797fde1..1fee2476597be0bb809d14d7dce28b83eb3cf82d 100644 (file)
@@ -418,7 +418,7 @@ void
 agen(Node *n, Node *res)
 {
        Node *nl, *nr;
-       Node n1, n2, n3, tmp, n4;
+       Node n1, n2, n3, tmp, n4, n5;
        Prog *p1;
        uint32 w;
        uint64 v;
@@ -518,13 +518,12 @@ agen(Node *n, Node *res)
                if(isconst(nr, CTINT)) {
                        v = mpgetfix(nr->val.u.xval);
                        if(isslice(nl->type)) {
-
                                if(!debug['B'] && !n->etype) {
                                        n1 = n3;
                                        n1.op = OINDREG;
                                        n1.type = types[tptr];
                                        n1.xoffset = Array_nel;
-                                       nodconst(&n2, types[TUINT64], v);
+                                       nodconst(&n2, types[TUINT32], v);
                                        gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
                                        p1 = gbranch(optoas(OGT, types[TUINT32]), T);
                                        ginscall(panicindex, 0);
@@ -536,13 +535,6 @@ agen(Node *n, Node *res)
                                n1.type = types[tptr];
                                n1.xoffset = Array_array;
                                gmove(&n1, &n3);
-                       } else
-                       if(!debug['B'] && !n->etype) {
-                               if(v < 0)
-                                       yyerror("out of bounds on array");
-                               else
-                               if(v >= nl->type->bound)
-                                       yyerror("out of bounds on array");
                        }
 
                        nodconst(&n2, types[tptr], v*w);
@@ -564,15 +556,28 @@ agen(Node *n, Node *res)
 
                if(!debug['B'] && !n->etype) {
                        // check bounds
+                       n5.op = OXXX;
+                       t = types[TUINT32];
                        if(isslice(nl->type)) {
                                n1 = n3;
                                n1.op = OINDREG;
-                               n1.type = types[tptr];
+                               n1.type = types[TUINT32];
                                n1.xoffset = Array_nel;
-                       } else
-                               nodconst(&n1, types[TUINT64], nl->type->bound);
-                       gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
-                       p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+                               if(is64(nr->type)) {
+                                       t = types[TUINT64];
+                                       regalloc(&n5, t, N);
+                                       gmove(&n1, &n5);
+                                       n1 = n5;
+                               }
+                       } else {
+                               if(is64(nr->type))
+                                       t = types[TUINT64];
+                               nodconst(&n1, t, nl->type->bound);
+                       }
+                       gins(optoas(OCMP, t), &n2, &n1);
+                       p1 = gbranch(optoas(OLT, t), T);
+                       if(n5.op != OXXX)
+                               regfree(&n5);
                        ginscall(panicindex, 0);
                        patch(p1, pc);
                }
index c7a4a642e64ccfe7ae9ee0ecdefbce45f4151c23..46ca326745de7db4ef830fc14d04dde8d2689199 100644 (file)
@@ -1115,44 +1115,62 @@ getargs(NodeList *nn, Node *reg, int n)
 void
 cmpandthrow(Node *nl, Node *nr)
 {
-       vlong cl, cr;
+       vlong cl;
        Prog *p1;
        int op;
        Node *c;
+       Type *t;
+       Node n1;
+       
+       if(nl->op == OCONV && is64(nl->type))
+               nl = nl->left;
+       if(nr->op == OCONV && is64(nr->type))
+               nr = nr->left;
 
        op = OLE;
        if(smallintconst(nl)) {
                cl = mpgetfix(nl->val.u.xval);
                if(cl == 0)
                        return;
-               if(smallintconst(nr)) {
-                       cr = mpgetfix(nr->val.u.xval);
-                       if(cl > cr) {
-                               if(throwpc == nil) {
-                                       throwpc = pc;
-                                       ginscall(panicslice, 0);
-                               } else
-                                       patch(gbranch(AJMP, T), throwpc);
-                       }
+               if(smallintconst(nr))
                        return;
-               }
-
                // put the constant on the right
                op = brrev(op);
                c = nl;
                nl = nr;
                nr = c;
        }
-
-       gins(optoas(OCMP, types[TUINT32]), nl, nr);
+       if(is64(nr->type) && smallintconst(nr))
+               nr->type = types[TUINT32];
+
+       n1.op = OXXX;
+       t = types[TUINT32];
+       if(is64(nl->type) || is64(nr->type)) {
+               // two 64-bit is just a 64-bit compare,
+               // but one 32 and one 64 needs to copy
+               // the 32 into a register to get the full comparison.
+               t = types[TUINT64];
+               if(!is64(nl->type) && nl->op != OLITERAL) {
+                       regalloc(&n1, t, nl);
+                       gmove(nl, &n1);
+                       nl = &n1;
+               } else if(!is64(nr->type) && nr->op != OLITERAL) {
+                       regalloc(&n1, t, nr);
+                       gmove(nr, &n1);
+                       nr = &n1;
+               }
+       }
+       gins(optoas(OCMP, t), nl, nr);
+       if(n1.op != OXXX)
+               regfree(&n1);
        if(throwpc == nil) {
-               p1 = gbranch(optoas(op, types[TUINT32]), T);
+               p1 = gbranch(optoas(op, t), T);
                throwpc = pc;
                ginscall(panicslice, 0);
                patch(p1, pc);
        } else {
                op = brcom(op);
-               p1 = gbranch(optoas(op, types[TUINT32]), T);
+               p1 = gbranch(optoas(op, t), T);
                patch(p1, throwpc);
        }
 }
@@ -1312,6 +1330,7 @@ sliceslice:
                // if(lb[1] > old.nel[0]) goto throw;
                n2 = nodes[0];
                n2.xoffset += Array_nel;
+               n2.type = types[TUINT32];
                cmpandthrow(&nodes[1], &n2);
 
                // ret.nel = old.nel[0]-lb[1];
@@ -1331,6 +1350,7 @@ sliceslice:
                // if(hb[2] > old.cap[0]) goto throw;
                n2 = nodes[0];
                n2.xoffset += Array_cap;
+               n2.type = types[TUINT32];
                cmpandthrow(&nodes[2], &n2);
 
                // if(lb[1] > hb[2]) goto throw;
index 52ff6fdea2d347a546ad8b5c9fa807ea97c19140..51c9cac6545faf366e7ba553e002d21d05a8f276 100644 (file)
@@ -1716,7 +1716,7 @@ sudoaddable(int as, Node *n, Addr *a)
        int o, i, w;
        int oary[10];
        int64 v;
-       Node n1, n2, n3, *nn, *l, *r;
+       Node n1, n2, n3, n4, *nn, *l, *r;
        Node *reg, *reg1;
        Prog *p1;
        Type *t;
@@ -1836,9 +1836,6 @@ oindex:
                break;
        }
 
-//     if(sudoaddable(as, l, a))
-//             goto oindex_sudo;
-
        cleani += 2;
        reg = &clean[cleani-1];
        reg1 = &clean[cleani-2];
@@ -1879,16 +1876,29 @@ oindex:
 
        // check bounds
        if(!debug['B'] && !n->etype) {
+               // check bounds
+               n4.op = OXXX;
+               t = types[TUINT32];
                if(o & ODynam) {
                        n2 = *reg;
                        n2.op = OINDREG;
-                       n2.type = types[tptr];
+                       n2.type = types[TUINT32];
                        n2.xoffset = Array_nel;
+                       if(is64(r->type)) {
+                               t = types[TUINT64];
+                               regalloc(&n4, t, N);
+                               gmove(&n2, &n4);
+                               n2 = n4;
+                       }
                } else {
+                       if(is64(r->type))
+                               t = types[TUINT64];
                        nodconst(&n2, types[TUINT64], l->type->bound);
                }
-               gins(optoas(OCMP, types[TUINT32]), reg1, &n2);
-               p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+               gins(optoas(OCMP, t), reg1, &n2);
+               p1 = gbranch(optoas(OLT, t), T);
+               if(n4.op != OXXX)
+                       regfree(&n4);
                ginscall(panicindex, 0);
                patch(p1, pc);
        }
@@ -1915,15 +1925,6 @@ oindex_const:
        // can multiply by width statically
 
        v = mpgetfix(r->val.u.xval);
-       if(!debug['B'] && (o & ODynam) == 0) {
-               // array indexed by a constant bounds check
-               if(v < 0) {
-                       yyerror("out of bounds on array");
-               } else
-               if(v >= l->type->bound) {
-                       yyerror("out of bounds on array");
-               }
-       }
 
        if(sudoaddable(as, l, a))
                goto oindex_const_sudo;
index 8fbdc6ee72c1a01c3e7a3c77f9b6ceb74b1d22d7..519907aa6d07bd0ede1b0625ac627851896f2578 100644 (file)
@@ -591,13 +591,6 @@ agen(Node *n, Node *res)
                                n1.type = types[tptr];
                                n1.xoffset = Array_array;
                                gmove(&n1, &n3);
-                       } else
-                       if(!debug['B'] && !n->etype) {
-                               if(v < 0)
-                                       yyerror("out of bounds on array");
-                               else
-                               if(v >= nl->type->bound)
-                                       yyerror("out of bounds on array");
                        }
 
                        nodconst(&n2, types[tptr], v*w);
index 7fbbdd344182840a456dccfae65ac77dc9b25ec6..983c17f44feca1e44fa9fd0e8b9efc1ebcbfaf7b 100644 (file)
@@ -789,25 +789,58 @@ regcmp(const void *va, const void *vb)
 
 static Prog*   throwpc;
 
+// We're only going to bother inlining if we can
+// convert all the arguments to 32 bits safely.  Can we?
+static int
+fix64(NodeList *nn, int n)
+{
+       NodeList *l;
+       Node *r;
+       int i;
+       
+       l = nn;
+       for(i=0; i<n; i++) {
+               r = l->n->right;
+               if(is64(r->type) && !smallintconst(r)) {
+                       if(r->op == OCONV)
+                               r = r->left;
+                       if(is64(r->type))
+                               return 0;
+               }
+               l = l->next;
+       }
+       return 1;
+}
+
 void
 getargs(NodeList *nn, Node *reg, int n)
 {
        NodeList *l;
+       Node *r;
        int i;
 
        throwpc = nil;
 
        l = nn;
        for(i=0; i<n; i++) {
-               if(!smallintconst(l->n->right) && !isslice(l->n->right->type)) {
+               r = l->n->right;
+               if(is64(r->type)) {
+                       if(r->op == OCONV)
+                               r = r->left;
+                       else if(smallintconst(r))
+                               r->type = types[TUINT32];
+                       if(is64(r->type))
+                               fatal("getargs");
+               }
+               if(!smallintconst(r) && !isslice(r->type)) {
                        if(i < 3)       // AX CX DX
-                               nodreg(reg+i, l->n->right->type, D_AX+i);
+                               nodreg(reg+i, r->type, D_AX+i);
                        else
                                reg[i].op = OXXX;
-                       regalloc(reg+i, l->n->right->type, reg+i);
-                       cgen(l->n->right, reg+i);
+                       regalloc(reg+i, r->type, reg+i);
+                       cgen(r, reg+i);
                } else
-                       reg[i] = *l->n->right;
+                       reg[i] = *r;
                if(reg[i].local != 0)
                        yyerror("local used");
                reg[i].local = l->n->left->xoffset;
@@ -908,6 +941,8 @@ cgen_inline(Node *n, Node *res)
 slicearray:
        if(!sleasy(res))
                goto no;
+       if(!fix64(n->list, 5))
+               goto no;
        getargs(n->list, nodes, 5);
 
        // if(hb[3] > nel[1]) goto throw
@@ -990,6 +1025,8 @@ slicearray:
        return 1;
 
 sliceslice:
+       if(!fix64(n->list, narg))
+               goto no;
        ntemp.op = OXXX;
        if(!sleasy(n->list->n->right)) {
                Node *n0;
index 3e2d98872589aa30859a986ea1102f25c8aabc62..ce86e12e5f61b912bb50e4dd66f430fc61052fb3 100644 (file)
@@ -75,9 +75,9 @@ char *runtimeimport =
        "func \"\".selectdefault (sel *uint8) bool\n"
        "func \"\".selectgo (sel *uint8)\n"
        "func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
-       "func \"\".sliceslice1 (old []any, lb int, width int) []any\n"
-       "func \"\".sliceslice (old []any, lb int, hb int, width int) []any\n"
-       "func \"\".slicearray (old *any, nel int, lb int, hb int, width int) []any\n"
+       "func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
+       "func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
+       "func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
        "func \"\".closure ()\n"
        "func \"\".int64div (? int64, ? int64) int64\n"
        "func \"\".uint64div (? uint64, ? uint64) uint64\n"
index 479e7dd6b717048f18903d8d2b7191460bf59f6b..a3405e078c3941028ec8e295b087863ac3e9c0b1 100644 (file)
@@ -1092,6 +1092,12 @@ smallintconst(Node *n)
        case TBOOL:
        case TPTR32:
                return 1;
+       case TINT64:
+       case TUINT64:
+               if(mpcmpfixfix(n->val.u.xval, minintval[TINT32]) < 0
+               || mpcmpfixfix(n->val.u.xval, maxintval[TINT32]) > 0)
+                       break;
+               return 1;
        }
        return 0;
 }
index 67375adb173511452612dc36e190e82d3c99aa60..40325500566b1272ff4ee96fb00b3aa1eface4f6 100644 (file)
@@ -536,7 +536,7 @@ mpgetfix(Mpint *a)
        vlong v;
 
        if(a->ovf) {
-               yyerror("ovf in mpgetfix");
+               yyerror("constant overflow");
                return 0;
        }
 
index 5783faafda21a1cd436acfbdff0be3c8648729a7..253134476e5377d14ffa4f6a813558e6575f96f7 100644 (file)
@@ -99,9 +99,9 @@ func selectdefault(sel *byte) (selected bool)
 func selectgo(sel *byte)
 
 func makeslice(typ *byte, nel int64, cap int64) (ary []any)
-func sliceslice1(old []any, lb int, width int) (ary []any)
-func sliceslice(old []any, lb int, hb int, width int) (ary []any)
-func slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
+func sliceslice1(old []any, lb uint64, width uint64) (ary []any)
+func sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
+func slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary []any)
 
 func closure() // has args, but compiler fills in
 
index b1991333ca0641cf40076bc5f87e9249080d66e9..1910aa6f90c374b207558d924b2a2c4a062cb3cf 100644 (file)
@@ -561,7 +561,7 @@ reswitch:
                        goto error;
 
                case TARRAY:
-                       defaultlit(&n->right, types[TUINT]);
+                       defaultlit(&n->right, T);
                        if(n->right->type != T && !isint[n->right->type->etype])
                                yyerror("non-integer array index %#N", n->right);
                        n->type = t->type;
@@ -635,8 +635,8 @@ reswitch:
                typecheck(&n->right->left, Erv);
                typecheck(&n->right->right, Erv);
                defaultlit(&n->left, T);
-               defaultlit(&n->right->left, types[TUINT]);
-               defaultlit(&n->right->right, types[TUINT]);
+               defaultlit(&n->right->left, T);
+               defaultlit(&n->right->right, T);
                if(isfixedarray(n->left->type)) {
                        // Insert explicit & before fixed array
                        // so that back end knows to move to heap.
index b21b7b3e8b716f9f193473f2ed99c5601254dfb7..775bcec9c6816b449e5f0bc344f4ab79f8a0f586 100644 (file)
@@ -565,6 +565,7 @@ walkexpr(Node **np, NodeList **init)
        NodeList *ll, *lr, *lpost;
        Type *t;
        int et;
+       int64 v, v1, v2, len;
        int32 lno;
        Node *n, *fn;
        char buf[100], *p;
@@ -1023,6 +1024,18 @@ walkexpr(Node **np, NodeList **init)
                if((1<<(8*n->right->type->width)) <= n->left->type->bound)
                        n->etype = 1;
 
+               // check for static out of bounds
+               if(isconst(n->right, CTINT) && !n->etype) {
+                       v = mpgetfix(n->right->val.u.xval);
+                       len = 1LL<<60;
+                       t = n->left->type;
+                       if(t != T && isptr[t->etype])
+                               t = t->type;
+                       if(isfixedarray(t))
+                               len = t->bound;
+                       if(v < 0 || v >= (1LL<<31) || v >= len)
+                               yyerror("index out of bounds");
+               }
                goto ret;
 
        case OINDEXMAP:
@@ -1039,15 +1052,48 @@ walkexpr(Node **np, NodeList **init)
                goto ret;
 
        case OSLICE:
+       case OSLICEARR:
                walkexpr(&n->left, init);
                n->left = safeexpr(n->left, init);
                walkexpr(&n->right->left, init);
                n->right->left = safeexpr(n->right->left, init);
                walkexpr(&n->right->right, init);
                n->right->right = safeexpr(n->right->right, init);
+
+               len = 1LL<<60;
+               t = n->left->type;
+               if(t != T && isptr[t->etype])
+                       t = t->type;
+               if(isfixedarray(t))
+                       len = t->bound;
+
+               // check for static out of bounds
+               // NOTE: v > len not v >= len.
+               v1 = -1;
+               v2 = -1;
+               if(isconst(n->right->left, CTINT)) {
+                       v1 = mpgetfix(n->right->left->val.u.xval);
+                       if(v1 < 0 || v1 >= (1LL<<31) || v1 > len) {
+                               yyerror("slice index out of bounds");
+                               v1 = -1;
+                       }
+               }
+               if(isconst(n->right->right, CTINT)) {
+                       v2 = mpgetfix(n->right->right->val.u.xval);
+                       if(v2 < 0 || v2 >= (1LL<<31) || v2 > len) {
+                               yyerror("slice index out of bounds");
+                               v2 = -1;
+                       }
+               }
+               if(v1 >= 0 && v2 >= 0 && v1 > v2)
+                       yyerror("inverted slice range");
+               
+               if(n->op == OSLICEARR)
+                       goto slicearray;
+
                // dynamic slice
-               // sliceslice(old []any, lb int, hb int, width int) (ary []any)
-               // sliceslice1(old []any, lb int, width int) (ary []any)
+               // sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
+               // sliceslice1(old []any, lb uint64, width uint64) (ary []any)
                t = n->type;
                if(n->right->right != N) {
                        fn = syslook("sliceslice", 1);
@@ -1055,8 +1101,8 @@ walkexpr(Node **np, NodeList **init)
                        argtype(fn, t->type);                   // any-2
                        n = mkcall1(fn, t, init,
                                n->left,
-                               conv(n->right->left, types[TINT]),
-                               conv(n->right->right, types[TINT]),
+                               conv(n->right->left, types[TUINT64]),
+                               conv(n->right->right, types[TUINT64]),
                                nodintconst(t->type->width));
                } else {
                        fn = syslook("sliceslice1", 1);
@@ -1064,20 +1110,14 @@ walkexpr(Node **np, NodeList **init)
                        argtype(fn, t->type);                   // any-2
                        n = mkcall1(fn, t, init,
                                n->left,
-                               conv(n->right->left, types[TINT]),
+                               conv(n->right->left, types[TUINT64]),
                                nodintconst(t->type->width));
                }
                goto ret;
 
-       case OSLICEARR:
-               walkexpr(&n->left, init);
-               n->left = safeexpr(n->left, init);
-               walkexpr(&n->right->left, init);
-               n->right->left = safeexpr(n->right->left, init);
-               walkexpr(&n->right->right, init);
-               n->right->right = safeexpr(n->right->right, init);
+       slicearray:
                // static slice
-               // slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
+               // slicearray(old *any, uint64 nel, lb uint64, hb uint64, width uint64) (ary []any)
                t = n->type;
                fn = syslook("slicearray", 1);
                argtype(fn, n->left->type);     // any-1
@@ -1085,16 +1125,16 @@ walkexpr(Node **np, NodeList **init)
                if(n->right->right == N)
                        r = nodintconst(n->left->type->bound);
                else
-                       r = conv(n->right->right, types[TINT]);
+                       r = conv(n->right->right, types[TUINT64]);
                n = mkcall1(fn, t, init,
                        nod(OADDR, n->left, N), nodintconst(n->left->type->bound),
-                       conv(n->right->left, types[TINT]),
+                       conv(n->right->left, types[TUINT64]),
                        r,
                        nodintconst(t->type->width));
                goto ret;
 
        case OCONVSLICE:
-               // slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
+               // slicearray(old *any, uint64 nel, lb uint64, hb uint64, width uint64) (ary []any)
                fn = syslook("slicearray", 1);
                argtype(fn, n->left->type->type);               // any-1
                argtype(fn, n->type->type);                     // any-2
index 4162b8daa27809b86274e8299b3ce5a0f846f1aa..67e44e93c092e324e4f9d9a9b55870ce920dad21 100644 (file)
@@ -39,9 +39,9 @@ void
        }
 }
 
-// sliceslice(old []any, lb int, hb int, width int) (ary []any);
+// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any);
 void
-·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
+·sliceslice(Slice old, uint64 lb, uint64 hb, uint64 width, Slice ret)
 {
        if(hb > old.cap || lb > hb) {
                if(debug) {
@@ -86,9 +86,9 @@ void
        }
 }
 
-// sliceslice1(old []any, lb int, width int) (ary []any);
+// sliceslice1(old []any, lb uint64, width uint64) (ary []any);
 void
-·sliceslice1(Slice old, uint32 lb, uint32 width, Slice ret)
+·sliceslice1(Slice old, uint64 lb, uint64 width, Slice ret)
 {
        if(lb > old.len) {
                if(debug) {
@@ -129,9 +129,9 @@ void
        }
 }
 
-// slicearray(old *any, nel int, lb int, hb int, width int) (ary []any);
+// slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary []any);
 void
-·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Slice ret)
+·slicearray(byte* old, uint64 nel, uint64 lb, uint64 hb, uint64 width, Slice ret)
 {
        if(nel > 0 && old == nil) {
                // crash if old == nil.
diff --git a/test/index.go b/test/index.go
new file mode 100644 (file)
index 0000000..a91294c
--- /dev/null
@@ -0,0 +1,224 @@
+// $G $D/$F.go && $L $F.$A &&
+// ./$A.out -pass 0 >tmp.go && $G tmp.go && $L -o tmp1.$A tmp.$A && ./tmp1.$A &&
+// ./$A.out -pass 1 >tmp.go && errchk $G -e tmp.go &&
+// ./$A.out -pass 2 >tmp.go && errchk $G -e tmp.go
+// rm -f tmp.go
+
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Generate test of index and slice bounds checks.
+
+package main
+
+import (
+       "bufio"
+       "flag"
+       "fmt"
+       "os"
+)
+
+const prolog = `
+
+package main
+
+import (
+       "runtime"
+)
+
+type quad struct { x, y, z, w int }
+
+const (
+       cj = 11
+       ci int = 12
+       ci32 int32 = 13
+       ci64 int64 = 14
+       ci64big int64 = 1<<31
+       ci64bigger int64 = 1<<32
+       chuge = 1<<100
+
+       cnj = -2
+       cni int = -3
+       cni32 int32 = -4
+       cni64 int64 = -5
+       cni64big int64 = -1<<31
+       cni64bigger int64 = -1<<32
+       cnhuge = -1<<100
+)
+
+var j int = 20
+var i int = 21
+var i32 int32 = 22
+var i64 int64 = 23
+var i64big int64 = 1<<31
+var i64bigger int64 = 1<<32
+var huge uint64 = 1<<64 - 1
+
+var nj int = -10
+var ni int = -11
+var ni32 int32 = -12
+var ni64 int64 = -13
+var ni64big int64 = -1<<31
+var ni64bigger int64 = -1<<32
+var nhuge int64 = -1<<63
+
+var si []int = make([]int, 10)
+var ai [10]int
+var pai *[10]int = &ai
+
+var sq []quad = make([]quad, 10)
+var aq [10]quad
+var paq *[10]quad = &aq
+
+type T struct {
+       si []int
+       ai [10]int
+       pai *[10]int
+       sq []quad
+       aq [10]quad
+       paq *[10]quad
+}
+
+var t = T{si, ai, pai, sq, aq, paq}
+
+var pt = &T{si, ai, pai, sq, aq, paq}
+
+// test that f panics
+func test(f func(), s string) {
+       defer func() {
+               if err := recover(); err == nil {
+                       _, file, line, _ := runtime.Caller(2)
+                       bug()
+                       print(file, ":", line, ": ", s, " did not panic\n")
+               }
+       }()
+       f()
+}
+
+var X interface{}
+func use(y interface{}) {
+       X = y
+}
+
+var didBug = false
+
+func bug() {
+       if !didBug {
+               didBug = true
+               println("BUG")
+       }
+}
+
+func main() {
+`
+
+// Passes:
+//     0 - dynamic checks
+//     1 - static checks of invalid constants (cannot assign to types)
+//     2 - static checks of array bounds
+var pass = flag.Int("pass", 0, "which test (0,1,2)")
+
+func testExpr(b *bufio.Writer, expr string) {
+       if *pass == 0 {
+               fmt.Fprintf(b, "\ttest(func(){use(%s)}, %q)\n", expr, expr)
+       } else {
+               fmt.Fprintf(b, "\tuse(%s)  // ERROR \"index|overflow\"\n", expr)
+       }
+}
+
+func main() {
+       b := bufio.NewWriter(os.Stdout)
+
+       flag.Parse()
+       
+       if *pass == 0 {
+               fmt.Fprint(b, "// $G $D/$F.go && $L $F.$A && ./$A.out\n\n")
+       } else {
+               fmt.Fprint(b, "// errchk $G -e $D/$F.go\n\n")
+       }
+       fmt.Fprint(b, prolog)
+       
+       var choices = [][]string{
+               // Direct value, fetch from struct, fetch from struct pointer.
+               // The last two cases get us to oindex_const_sudo in gsubr.c.
+               []string{"", "t.", "pt."},
+               
+               // Array, pointer to array, slice.
+               []string{"a", "pa", "s"},
+
+               // Element is int, element is quad (struct).
+               // This controls whether we end up in gsubr.c (i) or cgen.c (q).
+               []string{"i", "q"},
+
+               // Variable or constant.
+               []string{"", "c"},
+
+               // Positive or negative.
+               []string{"", "n"},
+
+               // Size of index.
+               []string{"j", "i", "i32", "i64", "i64big", "i64bigger", "huge"},
+       }
+       
+       forall(choices, func(x []string) {
+               p, a, e, c, n, i := x[0], x[1], x[2], x[3], x[4], x[5]
+
+               // Pass: dynamic=0, static=1, 2.
+               // Which cases should be caught statically?
+               // Only constants, obviously.
+               // Beyond that, must be one of these:
+               //      indexing into array or pointer to array
+               //      negative constant
+               //      large constant
+               thisPass := 0
+               if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge") {
+                       if i == "huge" {
+                               // Due to a detail of 6g's internals,
+                               // the huge constant errors happen in an
+                               // earlier pass than the others and inhibits
+                               // the next pass from running.
+                               // So run it as a separate check.
+                               thisPass = 1
+                       } else {
+                               thisPass = 2
+                       }
+               }
+
+               // Only print the test case if it is appropriate for this pass.
+               if thisPass == *pass {
+                       pae := p+a+e
+                       cni := c+n+i
+                       
+                       // Index operation
+                       testExpr(b, pae + "[" + cni + "]")
+                       
+                       // Slice operation.
+                       // Low index 0 is a special case in ggen.c
+                       // so test both 0 and 1.
+                       testExpr(b, pae + "[0:" + cni + "]")
+                       testExpr(b, pae + "[1:" + cni + "]")
+                       testExpr(b, pae + "[" + cni + ":]")
+                       testExpr(b, pae + "[" + cni + ":" + cni + "]")
+               }
+       })
+
+       fmt.Fprintln(b, "}")
+       b.Flush()
+}
+
+func forall(choices [][]string, f func([]string)) {
+       x := make([]string, len(choices))
+       
+       var recurse func(d int)
+       recurse = func(d int) {
+               if d >= len(choices) {
+                       f(x)
+                       return
+               }
+               for _, x[d] = range choices[d] {
+                       recurse(d+1)
+               }
+       }
+       recurse(0)
+}
index 496909f35230f6c6f825153166403e0bf69a923a..c95af8f62f836825e399e7459a6b230a6a1d6bbd 100644 (file)
@@ -52,7 +52,9 @@ func test2() {
 
 func test3() {
        defer mustRecover("slice")
-       println(x[11:9])
+       var lo = 11
+       var hi = 9
+       println(x[lo:hi])
 }
 
 func test4() {