Bug 33219

Summary: [GLSL bisected] implicit sized array triggers segfault in ir_to_mesa_visitor::copy_propagate
Product: Mesa Reporter: Gordon Jin <gordon.jin>
Component: glsl-compilerAssignee: Ian Romanick <idr>
Status: VERIFIED FIXED QA Contact:
Severity: major    
Priority: high CC: vlee
Version: 7.10Keywords: regression
Hardware: All   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments: new piglit test case

Description Gordon Jin 2011-01-17 17:54:41 UTC
Created attachment 42140 [details]
new piglit test case

The attached shader gets segfault. It's a recent regression.

(gdb) bt
#0  0xb7fff424 in __kernel_vsyscall ()
#1  0x42c0fd71 in raise () from /lib/libc.so.6
#2  0x42c1164a in abort () from /lib/libc.so.6
#3  0x42c4dd9d in __libc_message () from /lib/libc.so.6
#4  0x42c541e1 in malloc_printerr () from /lib/libc.so.6
#5  0xb7a3b640 in _talloc_free () from /usr/lib/libtalloc.so.2
#6  0xb7be534d in ir_to_mesa_visitor::copy_propagate (this=0xbffff1b0)
    at program/ir_to_mesa.cpp:2750
#7  0xb7be5fcc in get_mesa_program (ctx=0x806b688, prog=0x8432888)
    at program/ir_to_mesa.cpp:2852
#8  _mesa_ir_link_shader (ctx=0x806b688, prog=0x8432888)
    at program/ir_to_mesa.cpp:3037
#9  0xb7ab46e0 in brw_link_shader (ctx=0x806b688, prog=0x8432888)
    at brw_fs.cpp:156
#10 0xb7be3811 in _mesa_glsl_link_shader (ctx=0x806b688, prog=0x8432888)
    at program/ir_to_mesa.cpp:3191
#11 0xb7b2f1f9 in link_program (ctx=0x806b688, program=<value optimized out>)
    at main/shaderapi.c:885
#12 0x0804c048 in link_and_use_shaders ()
    at /root/gordon/piglit/tests/shaders/shader_runner.c:497
#13 0x0804d211 in piglit_init (argc=2, argv=0xbffff454)
    at /root/gordon/piglit/tests/shaders/shader_runner.c:864
#14 0x0804f683 in main (argc=2, argv=0xbffff454)
    at /root/gordon/piglit/tests/util/piglit-framework.c:116


It's introduced by:
7772a34f3aedfa8ef58ad5f912f56bd5adf27057
Author: Vinson Lee <vlee@vmware.com>
Date:   Fri Jan 14 16:18:52 2011 -0800

    mesa: Dynamically allocate acp array in ir_to_mesa_visitor::copy_propagate.
    
    Fixes these MSVC errors.
    ir_to_mesa.cpp(2644) : error C2057: expected constant expression
    ir_to_mesa.cpp(2644) : error C2466: cannot allocate an array of constant size 0
    ir_to_mesa.cpp(2644) : error C2133: 'acp' : unknown size
Comment 1 Ian Romanick 2011-01-25 11:06:27 UTC
I did a little debugging on this, and I suspect the problem was added when the copy propagation pass was added.  The acp buffer is being over-run.  It seems the expectation that this->next_temp is greater than any in-use register index is not being held.  The assertion below fails for this test case.

#3  0x00007ffff5599bb2 in ir_to_mesa_visitor::copy_propagate (this=0x7fffffffdcb0) at program/ir_to_mesa.cpp:2657
(gdb) print inst->dst_reg.index
$3 = 2
(gdb) print this->next_temp
$4 = 2

As a result, the buffer gets over-run at either line 2729 or 2746.

This probably wouldn't crash without dynamic memory allocation 
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 786fdfb..ddcf883 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -2652,6 +2652,8 @@ ir_to_mesa_visitor::copy_propagate(void)
 
    foreach_iter(exec_list_iterator, iter, this->instructions) {
       ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
+ 
+      assert(inst->dst_reg.index < this->next_temp);
 
       /* First, do any copy propagation possible into the src regs. */
       for (int r = 0; r < 3; r++) {
Comment 2 Ian Romanick 2011-01-25 11:18:31 UTC
With a little more digging, it seems that there is still a variable in the linked program with an unset array size.  This causes type_size to return 0, and next_temp does not get advanced.  This should not be able to happen due to checks in the linker for 0-sized arrays.

diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 786fdfb..7b5b424 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -651,6 +651,7 @@ type_size(const struct glsl_type *type)
         return 1;
       }
    case GLSL_TYPE_ARRAY:
+      assert(type->length > 0);
       return type_size(type->fields.array) * type->length;
    case GLSL_TYPE_STRUCT:
       size = 0;
Comment 3 Ian Romanick 2011-01-25 13:41:49 UTC
I added two piglit test cases that reproduce this and a related bug.  The following patch series should fix both.

I'm leaving the bug open but resetting the version to 7.10 until the patches are cherry picked.

commit 0f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8e
Author: Ian Romanick <ian.d.romanick@intel.com>
Date:   Tue Jan 25 12:06:18 2011 -0800

    linker: Propagate max_array_access while linking functions
    
    Update the max_array_access of a global as functions that use that
    global are pulled into the linked shader.
    
    Fixes piglit test glsl-fs-implicit-array-size-01 and bugzilla #33219.
    
    NOTE: This is a candidate for the 7.9 and 7.10 branches.

commit c87e9ef4d291b3fc18f7af2c7a7646b9a860f4af
Author: Ian Romanick <ian.d.romanick@intel.com>
Date:   Tue Jan 25 12:04:08 2011 -0800

    linker: Set sizes for non-global arrays as well
    
    Previously only global arrays with implicit sizes would be patched.
    This causes all arrays that are actually accessed to be sized.
    
    Fixes piglit test glsl-fs-implicit-array-size-02.
    
    NOTE: This is a candidate for the 7.9 and 7.10 branches.
Comment 4 Ian Romanick 2011-02-04 16:56:31 UTC
Fixed by 2b115017 (7.9) and 3370f9b6 (7.10).
Comment 5 Gordon Jin 2011-02-11 17:58:45 UTC
verified

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.