i915: Increase maximum program size to the hardware limits.
authorEric Anholt <eric@anholt.net>
Thu, 30 Jul 2009 07:03:21 +0000 (00:03 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 1 Oct 2009 21:31:03 +0000 (14:31 -0700)
This fixes potential heap trashing if the program of choice exceeds limits,
and fixes the native instructions limit being lower than what can be
used by valid programs.

src/mesa/drivers/dri/i915/i915_context.h
src/mesa/drivers/dri/i915/i915_program.c

index 8de4a9d0d3625c2f9cfff5f8d6c82813ea8427d4..082d614442535a26ba8c0cbf334d589aa86ef5d9 100644 (file)
@@ -121,10 +121,14 @@ enum {
 #define I915_MAX_CONSTANT      32
 #define I915_CONSTANT_SIZE     (2+(4*I915_MAX_CONSTANT))
 
+#define I915_MAX_INSN          (I915_MAX_DECL_INSN + \
+                               I915_MAX_TEX_INSN + \
+                               I915_MAX_ALU_INSN)
 
-#define I915_PROGRAM_SIZE      192
-
-#define I915_MAX_INSN          (I915_MAX_TEX_INSN+I915_MAX_ALU_INSN)
+/* Maximum size of the program packet, which matches the limits on
+ * decl, tex, and ALU instructions.
+ */
+#define I915_PROGRAM_SIZE      (I915_MAX_INSN * 3 + 1)
 
 /* Hardware version of a parsed fragment program.  "Derived" from the
  * mesa fragment_program struct.
@@ -154,8 +158,9 @@ struct i915_fragment_program
     */
    GLcontext *ctx;
 
-   GLuint declarations[I915_PROGRAM_SIZE];
-   GLuint program[I915_PROGRAM_SIZE];
+   /* declarations contains the packet header. */
+   GLuint declarations[I915_MAX_DECL_INSN * 3 + 1];
+   GLuint program[(I915_MAX_TEX_INSN + I915_MAX_ALU_INSN) * 3];
 
    GLfloat constant[I915_MAX_CONSTANT][4];
    GLuint constant_flags[I915_MAX_CONSTANT];
index fd3019b234a1263bbc63687370e6caa56126bd05..e7908bd48fc3e33e30ac74ccf9b569e2292699cf 100644 (file)
@@ -130,6 +130,7 @@ i915_emit_decl(struct i915_fragment_program *p,
    *(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags);
    *(p->decl++) = D1_MBZ;
    *(p->decl++) = D2_MBZ;
+   assert(p->decl <= p->declarations + ARRAY_SIZE(p->declarations));
 
    p->nr_decl_insn++;
    return reg;
@@ -186,7 +187,7 @@ i915_emit_arith(struct i915_fragment_program * p,
       p->utemp_flag = old_utemp_flag;   /* restore */
    }
 
-   if (p->csr >= p->program + I915_PROGRAM_SIZE) {
+   if (p->csr >= p->program + ARRAY_SIZE(p->program)) {
       i915_program_error(p, "Program contains too many instructions");
       return UREG_BAD;
    }
@@ -275,7 +276,7 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
          p->register_phases[GET_UREG_NR(coord)] == p->nr_tex_indirect)
         p->nr_tex_indirect++;
 
-      if (p->csr >= p->program + I915_PROGRAM_SIZE) {
+      if (p->csr >= p->program + ARRAY_SIZE(p->program)) {
         i915_program_error(p, "Program contains too many instructions");
         return UREG_BAD;
       }
@@ -530,6 +531,9 @@ i915_upload_program(struct i915_context *i915,
    GLuint program_size = p->csr - p->program;
    GLuint decl_size = p->decl - p->declarations;
 
+   if (p->error)
+      return;
+
    /* Could just go straight to the batchbuffer from here:
     */
    if (i915->state.ProgramSize != (program_size + decl_size) ||