[Mesa-dev] [PATCH 1/4] mesa/main: fix MultiDrawElements[BaseVertex] validation of primcount

Ian Romanick idr at freedesktop.org
Thu Feb 23 01:49:22 UTC 2017


On 02/22/2017 11:04 AM, Nicolai Hähnle wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
> 
> primcount must be a GLsizei as in the signature for MultiDrawElements
> or bad things can happen.
> 
> Furthermore, an error should be flagged when primcount is negative
> (plus there is an argument about whether it should be flagged when
> primcount is 0, but let's worry about that separately).
> 
> Curiously, this code used to work somewhat correctly even when primcount
> was negative, because the loop that checks count[i] would iterate out of
> bounds and almost certainly hit a negative value at some point.
> 
> Found by an ASAN error in
> GL45-CTS.gtf32.GL3Tests.draw_elements_base_vertex.draw_elements_base_vertex_primcount
> 
> Note that the OpenGL spec seems to have s/primcount/drawcount/ at some
> point, and the code still reflects the old language.
> 
> Cc: mesa-stable at lists.freedesktop.org
> ---
>  src/mesa/main/api_validate.c | 41 +++++++++++++++++++++++++++++++++++++++--
>  src/mesa/main/api_validate.h |  2 +-
>  2 files changed, 40 insertions(+), 3 deletions(-)
> 
> diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
> index 1e8a714..5b05301 100644
> --- a/src/mesa/main/api_validate.c
> +++ b/src/mesa/main/api_validate.c
> @@ -716,26 +716,63 @@ _mesa_validate_DrawElements(struct gl_context *ctx,
>  
>  /**
>   * Error checking for glMultiDrawElements().  Includes parameter checking
>   * and VBO bounds checking.
>   * \return GL_TRUE if OK to render, GL_FALSE if error found
>   */
>  GLboolean
>  _mesa_validate_MultiDrawElements(struct gl_context *ctx,
>                                   GLenum mode, const GLsizei *count,
>                                   GLenum type, const GLvoid * const *indices,
> -                                 GLuint primcount)
> +                                 GLsizei primcount)
>  {
> -   unsigned i;
> +   GLsizei i;
>  
>     FLUSH_CURRENT(ctx, 0);
>  
> +   /*
> +    * Section 10.4 (Drawing Commands Using Vertex Arrays) of the OpenGL 4.5
> +    * (Compatibility Profile) spec defines MultiDrawElements as equivalent to:
> +    *
> +    *    if (mode, drawcount, or type is invalid)
> +    *       generate appropriate error
> +    *    else {
> +    *       for (int i = 0; i < drawcount; i++)
> +    *          DrawElementsOneInstance(mode, count[i], type,
> +    *                                  indices[i], 0, 0, 0);
> +    *    }
> +    *
> +    * However, it does not say when drawcount is invalid or what the
> +    * appropriate error would be.
> +    *
> +    * The same section does define the error condition for the similar
> +    * MultiDrawElementsIndirect:
> +    *
> +    *    "An INVALID_VALUE error is generated if drawcount is not positive."

There is blanket coverage for this.

Section 2.3.1 (Errors) of the OpenGL 4.5 Core Profile spec says:

   If a negative number is provided where an argument of type sizei or
   sizeiptr is specified, an INVALID_VALUE error is generated.

> +    *
> +    * It would make sense to apply the same condition here, but
> +    *
> +    * (1) this language was only introduced together with the *Indirect() draw
> +    *     calls and is quite far removed textually, and
> +    *
> +    * (2) GL45-CTS.gtf32.GL3Tests.draw_elements_base_vertex.draw_elements_base_vertex_primcount
> +    *     expects to get an error iff the value is negative.
> +    *
> +    * This looks like a gap in the spec, but until that is resolved, let's just
> +    * follow what the CTS expects.

The CTS is also expecting this (from the same section of the spec):

   In other cases, there are no side effects unless otherwise noted;
   the command which generates the error is ignored so that it has no
   effect on GL state or framebuffer contents.

If some count[i] would generate an error, the whole command must have no
side effects.

With the comment changed to reference the spec quotes, this patch is

Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>

> +    */
> +   if (primcount < 0) {
> +      _mesa_error(ctx, GL_INVALID_VALUE,
> +                  "glMultiDrawElements(primcount=%d)", primcount);
> +      return GL_FALSE;
> +   }
> +
>     for (i = 0; i < primcount; i++) {
>        if (count[i] < 0) {
>           _mesa_error(ctx, GL_INVALID_VALUE,
>                       "glMultiDrawElements(count)" );
>           return GL_FALSE;
>        }
>     }
>  
>     if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) {
>        return GL_FALSE;
> diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h
> index e94f02e..de520c9 100644
> --- a/src/mesa/main/api_validate.h
> +++ b/src/mesa/main/api_validate.h
> @@ -50,21 +50,21 @@ _mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei count);
>  
>  extern GLboolean
>  _mesa_validate_DrawElements(struct gl_context *ctx,
>  			    GLenum mode, GLsizei count, GLenum type,
>  			    const GLvoid *indices);
>  
>  extern GLboolean
>  _mesa_validate_MultiDrawElements(struct gl_context *ctx,
>                                   GLenum mode, const GLsizei *count,
>                                   GLenum type, const GLvoid * const *indices,
> -                                 GLuint primcount);
> +                                 GLsizei primcount);
>  
>  extern GLboolean
>  _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
>  				 GLuint start, GLuint end,
>  				 GLsizei count, GLenum type,
>  				 const GLvoid *indices);
>  
>  
>  extern GLboolean
>  _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
> 



More information about the mesa-dev mailing list