[Mesa-dev] Overflow of intel vertex buffer

Hodek, Roman roman.aud at siemens.com
Wed Mar 5 08:30:07 PST 2014


Hello all!

While debugging an application crash, we found a problem in mesa i915 buffer
allocation, and we think we at least have a workaround for this.

In more detail, the vertex buffers used in src/mesa/drivers/dri/i915/*.c, which
are pointed to by intel->prim.vb, usually have a size of INTEL_VB_SIZE
(alloc'ed by intel_get_prim_space() in intel_tris.c). And
intel->prim.current_offset is the offset where next data will be written.

Shortly before the crash we're hunting, we see in the debugger that
'current_offset' is greater than INTEL_VB_SIZE. Soon afterwards, some data
after the buffer are overwritten, and something else segfaults.

We can not say yet why 'current_offset' is wrong, but we suspect the alignments
like

      intel->prim.current_offset = intel->prim.start_offset =
ALIGN(intel->prim.start_offset, 128);

in e.g. intel_flush_prim() could be the cause. (Any better ideas on this?)

Anyway, to work around the most obvious problem, we modified the function
intel_get_current_max() in intel_render.c (patch below) to check for an
overflow, and reserve some space at the end, just to be sure. This at least
avoids the crashes we observe, and generally seems to increase robustness at
this spot.

Nevertheless it would be interesting what the root cause of the problem is...
any hints?

Roman


PS: please keep me in Cc:, I'm non subscribed to this list; thanks!



diff -u -ur mesa-10.0.3/src/mesa/drivers/dri/i915/intel_render.c
mesa-10.0.3-fix/src/mesa/drivers/dri/i915/intel_render.c
--- mesa-10.0.3/src/mesa/drivers/dri/i915/intel_render.c        2014-02-03
18:42:39.000000000 +0100
+++ mesa-10.0.3-fix/src/mesa/drivers/dri/i915/intel_render.c    2014-03-05
09:53:10.534481511 +0100
@@ -140,10 +140,16 @@
    if (intel->intelScreen->no_vbo) {
       ret = intel_batchbuffer_space(intel);
       ret = ret <= INTEL_NO_VBO_STATE_RESERVED ? 0 : ret -
INTEL_NO_VBO_STATE_RESERVED;
-   } else
-      ret = (INTEL_VB_SIZE - intel->prim.current_offset);
-
-   return ret / (intel->vertex_size * 4);
+   } else {
+      if (INTEL_VB_SIZE > intel->prim.current_offset)
+         ret = (INTEL_VB_SIZE - intel->prim.current_offset);
+      else
+         ret = 0;
+   }
+   ret /= (intel->vertex_size * 4);
+   if (ret > 4)
+      ret -= 4; // don't fill buffer to the end!
+   return ret;
 }

 #define LOCAL_VARS struct intel_context *intel = intel_context(ctx)


More information about the mesa-dev mailing list