[Mesa-dev] [PATCH] mesa: fixes for DrawRangeElements[BaseVertex] index validation

Roland Scheidegger sroland at vmware.com
Fri Jan 27 18:00:02 PST 2012


in check_index_bounds the comparison needs to be "greater equal" since
contrary to the name _MaxElement is the count of the array.
In vbo_exec_DrawRangeElementsBaseVertex, take into account the basevertex.
As far as I can tell it is completely ok (though maybe stupid) to have
start/end of 100/199, with _MaxElement being 100, if the basevertex
is -100 (since the start/end are prior to adding basevertex). The opposite
is also true (0/99 is not ok if _MaxElement is 100 and and basevertex is 100).
Previously we would have issued a warning in such cases and worse probably
"fixed" end to a bogus value.
Totally untested, found by code inspection when looking at bug 40361 (which
seems unrelated after all).
---
 src/mesa/main/api_validate.c  |    2 +-
 src/mesa/vbo/vbo_exec_array.c |   30 +++++++++++++++++++-----------
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index b6871d0..1ae491f 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -187,7 +187,7 @@ check_index_bounds(struct gl_context *ctx, GLsizei count, GLenum type,
    vbo_get_minmax_indices(ctx, &prim, &ib, &min, &max, 1);
 
    if ((int)(min + basevertex) < 0 ||
-       max + basevertex > ctx->Array.ArrayObj->_MaxElement) {
+       max + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
       /* the max element is out of bounds of one or more enabled arrays */
       _mesa_warning(ctx, "glDrawElements() index=%u is out of bounds (max=%u)",
                     max, ctx->Array.ArrayObj->_MaxElement);
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 9861b21..3e0fe20 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -885,17 +885,18 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
       end = MIN2(end, 0xffff);
    }
 
-   if (end >= ctx->Array.ArrayObj->_MaxElement) {
+   if ((int)(start + basevertex) < 0 ||
+       end + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
       /* the max element is out of bounds of one or more enabled arrays */
       warnCount++;
 
       if (warnCount < 10) {
-         _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
-                       "type 0x%x, indices=%p)\n"
+         _mesa_warning(ctx, "glDrawRangeElements[BaseVertex](start %u, end %u, count %d, "
+                       "type 0x%x, indices=%p, base %d)\n"
                        "\tend is out of bounds (max=%u)  "
                        "Element Buffer %u (size %d)\n"
                        "\tThis should probably be fixed in the application.",
-                       start, end, count, type, indices,
+                       start, end, count, type, indices, basevertex,
                        ctx->Array.ArrayObj->_MaxElement - 1,
                        ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
                        (int) ctx->Array.ArrayObj->ElementArrayBufferObj->Size);
@@ -913,14 +914,14 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
       if (0) {
          GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
                                              ctx->Array.ArrayObj->ElementArrayBufferObj);
-         if (max >= ctx->Array.ArrayObj->_MaxElement) {
+         if (max + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
             if (warnCount < 10) {
-               _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
-                             "count %d, type 0x%x, indices=%p)\n"
+               _mesa_warning(ctx, "glDrawRangeElements[BaseVertex](start %u, end %u, "
+                             "count %d, type 0x%x, indices=%p, base %d)\n"
                              "\tindex=%u is out of bounds (max=%u)  "
                              "Element Buffer %u (size %d)\n"
                              "\tSkipping the glDrawRangeElements() call",
-                             start, end, count, type, indices, max,
+                             start, end, count, type, indices, basevertex, max,
                              ctx->Array.ArrayObj->_MaxElement - 1,
                              ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
                              (int) ctx->Array.ArrayObj->ElementArrayBufferObj->Size);
@@ -928,13 +929,20 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
          }
          /* XXX we could also find the min index and compare to 'start'
           * to see if start is correct.  But it's more likely to get the
-          * upper bound wrong.
+          * upper bound wrong, at least for the non-BaseVertex variant...
           */
       }
 
       /* Set 'end' to the max possible legal value */
       assert(ctx->Array.ArrayObj->_MaxElement >= 1);
-      end = ctx->Array.ArrayObj->_MaxElement - 1;
+      /* XXX Could have positive uint overflow for both start and end too. */
+      if ((int)(ctx->Array.ArrayObj->_MaxElement - 1 - basevertex) < 0) {
+         return;
+      }
+      end = ctx->Array.ArrayObj->_MaxElement - 1 - basevertex;
+      if ((int)(start + basevertex) < 0) {
+         start = -basevertex;
+      }
 
       if (end < start) {
          return;
@@ -942,7 +950,7 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
    }
 
    if (0) {
-      printf("glDraw[Range]Elements{,BaseVertex}"
+      printf("glDrawRangeElements{,BaseVertex}"
 	     "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
 	     "base %d\n",
 	     start, end, type, count,
-- 
1.7.1



More information about the mesa-dev mailing list