glthread: fix a crash with incorrect glShaderSource parameters
[mesa.git] / src / mesa / main / marshal.c
index df1ab78cd5db62ac01f0171e9803bb057a19ae32..b2935f63753aa0486ea172b94ab6ca36155e6717 100644 (file)
@@ -111,7 +111,7 @@ _mesa_marshal_ShaderSource(GLuint shader, GLsizei count,
       measure_ShaderSource_strings(count, string, length, length_tmp);
    size_t total_cmd_size = fixed_cmd_size + length_size + total_string_length;
 
-   if (total_cmd_size <= MARSHAL_MAX_CMD_SIZE) {
+   if (total_cmd_size <= MARSHAL_MAX_CMD_SIZE && count > 0) {
       struct marshal_cmd_ShaderSource *cmd =
          _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_ShaderSource,
                                          total_cmd_size);
@@ -192,6 +192,7 @@ struct marshal_cmd_BufferData
    const GLvoid *data_external_mem;
    bool data_null; /* If set, no data follows for "data" */
    bool named;
+   bool ext_dsa;
    /* Next size bytes are GLubyte data[size] */
 };
 
@@ -211,7 +212,10 @@ _mesa_unmarshal_BufferData(struct gl_context *ctx,
    else
       data = (const void *) (cmd + 1);
 
-   if (cmd->named) {
+   if (cmd->ext_dsa) {
+      CALL_NamedBufferDataEXT(ctx->CurrentServerDispatch,
+                              (target_or_name, size, data, usage));
+   } else if (cmd->named) {
       CALL_NamedBufferData(ctx->CurrentServerDispatch,
                            (target_or_name, size, data, usage));
    } else {
@@ -227,10 +231,17 @@ _mesa_unmarshal_NamedBufferData(struct gl_context *ctx,
    unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData");
 }
 
+void
+_mesa_unmarshal_NamedBufferDataEXT(struct gl_context *ctx,
+                                   const struct marshal_cmd_BufferData *cmd)
+{
+   unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData");
+}
+
 static void
 _mesa_marshal_BufferData_merged(GLuint target_or_name, GLsizeiptr size,
                                 const GLvoid *data, GLenum usage, bool named,
-                                const char *func)
+                                bool ext_dsa, const char *func)
 {
    GET_CURRENT_CONTEXT(ctx);
    bool external_mem = !named &&
@@ -262,6 +273,7 @@ _mesa_marshal_BufferData_merged(GLuint target_or_name, GLsizeiptr size,
    cmd->usage = usage;
    cmd->data_null = !data;
    cmd->named = named;
+   cmd->ext_dsa = ext_dsa;
    cmd->data_external_mem = data;
 
    if (copy_data) {
@@ -275,7 +287,7 @@ void GLAPIENTRY
 _mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data,
                          GLenum usage)
 {
-   _mesa_marshal_BufferData_merged(target, size, data, usage, false,
+   _mesa_marshal_BufferData_merged(target, size, data, usage, false, false,
                                    "BufferData");
 }
 
@@ -283,18 +295,28 @@ void GLAPIENTRY
 _mesa_marshal_NamedBufferData(GLuint buffer, GLsizeiptr size,
                               const GLvoid * data, GLenum usage)
 {
-   _mesa_marshal_BufferData_merged(buffer, size, data, usage, true,
+   _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, false,
                                    "NamedBufferData");
 }
 
+void GLAPIENTRY
+_mesa_marshal_NamedBufferDataEXT(GLuint buffer, GLsizeiptr size,
+                                 const GLvoid *data, GLenum usage)
+{
+   _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, true,
+                                   "NamedBufferDataEXT");
+}
+
 
 /* BufferSubData: marshalled asynchronously */
 struct marshal_cmd_BufferSubData
 {
    struct marshal_cmd_base cmd_base;
-   GLenum target;
+   GLenum target_or_name;
    GLintptr offset;
    GLsizeiptr size;
+   bool named;
+   bool ext_dsa;
    /* Next size bytes are GLubyte data[size] */
 };
 
@@ -302,98 +324,94 @@ void
 _mesa_unmarshal_BufferSubData(struct gl_context *ctx,
                               const struct marshal_cmd_BufferSubData *cmd)
 {
-   const GLenum target = cmd->target;
+   const GLenum target_or_name = cmd->target_or_name;
    const GLintptr offset = cmd->offset;
    const GLsizeiptr size = cmd->size;
    const void *data = (const void *) (cmd + 1);
 
-   CALL_BufferSubData(ctx->CurrentServerDispatch,
-                      (target, offset, size, data));
+   if (cmd->ext_dsa) {
+      CALL_NamedBufferSubDataEXT(ctx->CurrentServerDispatch,
+                                 (target_or_name, offset, size, data));
+   } else if (cmd->named) {
+      CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
+                              (target_or_name, offset, size, data));
+   } else {
+      CALL_BufferSubData(ctx->CurrentServerDispatch,
+                         (target_or_name, offset, size, data));
+   }
 }
 
-void GLAPIENTRY
-_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
-                            const GLvoid * data)
+void
+_mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx,
+                                   const struct marshal_cmd_BufferSubData *cmd)
+{
+   unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData");
+}
+
+void
+_mesa_unmarshal_NamedBufferSubDataEXT(struct gl_context *ctx,
+                                      const struct marshal_cmd_BufferSubData *cmd)
+{
+   unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData");
+}
+
+static void
+_mesa_marshal_BufferSubData_merged(GLuint target_or_name, GLintptr offset,
+                                   GLsizeiptr size, const GLvoid *data,
+                                   bool named, bool ext_dsa, const char *func)
 {
    GET_CURRENT_CONTEXT(ctx);
    size_t cmd_size = sizeof(struct marshal_cmd_BufferSubData) + size;
+   debug_print_marshal(func);
 
-   debug_print_marshal("BufferSubData");
-   if (unlikely(size < 0)) {
-      _mesa_glthread_finish(ctx);
-      _mesa_error(ctx, GL_INVALID_VALUE, "BufferSubData(size < 0)");
+   if (unlikely(size < 0 || size > INT_MAX || cmd_size < 0 ||
+                cmd_size > MARSHAL_MAX_CMD_SIZE || !data ||
+                (named && target_or_name == 0))) {
+      _mesa_glthread_finish_before(ctx, func);
+      if (named) {
+         CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
+                                 (target_or_name, offset, size, data));
+      } else {
+         CALL_BufferSubData(ctx->CurrentServerDispatch,
+                            (target_or_name, offset, size, data));
+      }
       return;
    }
 
-   if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
-       cmd_size <= MARSHAL_MAX_CMD_SIZE) {
-      struct marshal_cmd_BufferSubData *cmd =
-         _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferSubData,
-                                         cmd_size);
-      cmd->target = target;
-      cmd->offset = offset;
-      cmd->size = size;
-      char *variable_data = (char *) (cmd + 1);
-      memcpy(variable_data, data, size);
-      _mesa_post_marshal_hook(ctx);
-   } else {
-      _mesa_glthread_finish(ctx);
-      CALL_BufferSubData(ctx->CurrentServerDispatch,
-                         (target, offset, size, data));
-   }
-}
-
+   struct marshal_cmd_BufferSubData *cmd =
+      _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferSubData,
+                                      cmd_size);
+   cmd->target_or_name = target_or_name;
+   cmd->offset = offset;
+   cmd->size = size;
+   cmd->named = named;
+   cmd->ext_dsa = ext_dsa;
 
-/* NamedBufferSubData: marshalled asynchronously */
-struct marshal_cmd_NamedBufferSubData
-{
-   struct marshal_cmd_base cmd_base;
-   GLuint name;
-   GLintptr offset;
-   GLsizei size;
-   /* Next size bytes are GLubyte data[size] */
-};
+   char *variable_data = (char *) (cmd + 1);
+   memcpy(variable_data, data, size);
+   _mesa_post_marshal_hook(ctx);
+}
 
-void
-_mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx,
-                                   const struct marshal_cmd_NamedBufferSubData *cmd)
+void GLAPIENTRY
+_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
+                            const GLvoid * data)
 {
-   const GLuint name = cmd->name;
-   const GLintptr offset = cmd->offset;
-   const GLsizei size = cmd->size;
-   const void *data = (const void *) (cmd + 1);
-
-   CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
-                           (name, offset, size, data));
+   _mesa_marshal_BufferSubData_merged(target, offset, size, data, false,
+                                      false, "BufferSubData");
 }
 
 void GLAPIENTRY
 _mesa_marshal_NamedBufferSubData(GLuint buffer, GLintptr offset,
                                  GLsizeiptr size, const GLvoid * data)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   size_t cmd_size = sizeof(struct marshal_cmd_NamedBufferSubData) + size;
-
-   debug_print_marshal("NamedBufferSubData");
-   if (unlikely(size < 0)) {
-      _mesa_glthread_finish(ctx);
-      _mesa_error(ctx, GL_INVALID_VALUE, "NamedBufferSubData(size < 0)");
-      return;
-   }
+   _mesa_marshal_BufferSubData_merged(buffer, offset, size, data, true,
+                                      false, "NamedBufferSubData");
+}
 
-   if (buffer > 0 && cmd_size <= MARSHAL_MAX_CMD_SIZE) {
-      struct marshal_cmd_NamedBufferSubData *cmd =
-         _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_NamedBufferSubData,
-                                         cmd_size);
-      cmd->name = buffer;
-      cmd->offset = offset;
-      cmd->size = size;
-      char *variable_data = (char *) (cmd + 1);
-      memcpy(variable_data, data, size);
-      _mesa_post_marshal_hook(ctx);
-   } else {
-      _mesa_glthread_finish(ctx);
-      CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
-                              (buffer, offset, size, data));
-   }
+void GLAPIENTRY
+_mesa_marshal_NamedBufferSubDataEXT(GLuint buffer, GLintptr offset,
+                                    GLsizeiptr size, const GLvoid * data)
+{
+   _mesa_marshal_BufferSubData_merged(buffer, offset, size, data, true,
+                                      true, "NamedBufferSubDataEXT");
 }