r600g/sb: Don't read junk after EOP
authorGlenn Kennard <glenn.kennard@gmail.com>
Thu, 27 Aug 2015 17:04:16 +0000 (19:04 +0200)
committerDave Airlie <airlied@redhat.com>
Fri, 28 Aug 2015 02:32:32 +0000 (12:32 +1000)
Shaders that contain instruction data after an instruction with EOP could end
up parsing that as an instruction, leading to various crashes and asserts in
SB as it gets very confused if it sees for instance a loop start instruction
jumping off to some random point.

Add a couple of asserts, and print EOP bit if set in old asm printer.

Signed-off-by: Glenn Kennard <glenn.kennard@gmail.com>
Cc: <mesa-stable@lists.freedesktop.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/drivers/r600/r600_asm.c
src/gallium/drivers/r600/sb/sb_bc_decoder.cpp
src/gallium/drivers/r600/sb/sb_bc_parser.cpp

index 762cc7fac441168882c683de312629331aa420eb..b514c58f9d8c520eaca302598b4a92dafa715844 100644 (file)
@@ -2029,6 +2029,8 @@ void r600_bytecode_disasm(struct r600_bytecode *bc)
                                        fprintf(stderr, "CND:%X ", cf->cond);
                                if (cf->pop_count)
                                        fprintf(stderr, "POP:%X ", cf->pop_count);
+                               if (cf->end_of_program)
+                                       fprintf(stderr, "EOP ");
                                fprintf(stderr, "\n");
                        }
                }
index 5e233f982ea3aa26ec2a28cc533c4b35e40e8524..5fe8f50aa4cef513cd80b23bc7d59afc280fa363 100644 (file)
@@ -32,6 +32,7 @@ int bc_decoder::decode_cf(unsigned &i, bc_cf& bc) {
        int r = 0;
        uint32_t dw0 = dw[i];
        uint32_t dw1 = dw[i+1];
+       assert(i+1 <= ndw);
 
        if ((dw1 >> 29) & 1) { // CF_ALU
                return decode_cf_alu(i, bc);
index 4879c036f9f2df586c5dd361cc6d790a59be006d..748aae29eebb754616c1972f9fbea83dae1d54eb 100644 (file)
@@ -95,7 +95,7 @@ int bc_parser::decode_shader() {
                if ((r = decode_cf(i, eop)))
                        return r;
 
-       } while (!eop || (i >> 1) <= max_cf);
+       } while (!eop || (i >> 1) < max_cf);
 
        return 0;
 }
@@ -769,6 +769,7 @@ int bc_parser::prepare_ir() {
 }
 
 int bc_parser::prepare_loop(cf_node* c) {
+       assert(c->bc.addr-1 < cf_map.size());
 
        cf_node *end = cf_map[c->bc.addr - 1];
        assert(end->bc.op == CF_OP_LOOP_END);
@@ -788,6 +789,7 @@ int bc_parser::prepare_loop(cf_node* c) {
 }
 
 int bc_parser::prepare_if(cf_node* c) {
+       assert(c->bc.addr-1 < cf_map.size());
        cf_node *c_else = NULL, *end = cf_map[c->bc.addr];
 
        BCP_DUMP(