Detect draws that would read outside the vertex buffer.

TRAC #12340 Signed-off-by: Nicolas Capens Signed-off-by: Daniel Koch Author: Andrew Lewycky git-svn-id: https://angleproject.googlecode.com/svn/trunk@308 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 8b9f4cc8
...@@ -1943,26 +1943,36 @@ void Context::lookupAttributeMapping(TranslatedAttribute *attributes) ...@@ -1943,26 +1943,36 @@ void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
} }
} }
void Context::applyVertexBuffer(GLint first, GLsizei count) GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
{ {
TranslatedAttribute translated[MAX_VERTEX_ATTRIBS]; TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
mVertexDataManager->preRenderValidate(first, count, translated); GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
lookupAttributeMapping(translated); if (err == GL_NO_ERROR)
{
lookupAttributeMapping(translated);
mBufferBackEnd->setupAttributesPreDraw(translated);
}
mBufferBackEnd->setupAttributesPreDraw(translated); return err;
} }
void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo) GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
{ {
TranslatedAttribute translated[MAX_VERTEX_ATTRIBS]; TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated); GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
lookupAttributeMapping(translated); if (err == GL_NO_ERROR)
{
lookupAttributeMapping(translated);
mBufferBackEnd->setupAttributesPreDraw(translated); mBufferBackEnd->setupAttributesPreDraw(translated);
}
return err;
} }
// Applies the indices and element array bindings to the Direct3D 9 device // Applies the indices and element array bindings to the Direct3D 9 device
...@@ -2423,7 +2433,13 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -2423,7 +2433,13 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
} }
applyState(mode); applyState(mode);
applyVertexBuffer(first, count);
GLenum err = applyVertexBuffer(first, count);
if (err != GL_NO_ERROR)
{
return error(err);
}
applyShaders(); applyShaders();
applyTextures(); applyTextures();
...@@ -2478,7 +2494,12 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* ...@@ -2478,7 +2494,12 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void*
return error(err); return error(err);
} }
applyVertexBuffer(indexInfo); err = applyVertexBuffer(indexInfo);
if (err != GL_NO_ERROR)
{
return error(err);
}
applyShaders(); applyShaders();
applyTextures(); applyTextures();
......
...@@ -351,8 +351,8 @@ class Context ...@@ -351,8 +351,8 @@ class Context
bool applyRenderTarget(bool ignoreViewport); bool applyRenderTarget(bool ignoreViewport);
void applyState(GLenum drawMode); void applyState(GLenum drawMode);
void applyVertexBuffer(GLint first, GLsizei count); GLenum applyVertexBuffer(GLint first, GLsizei count);
void applyVertexBuffer(const TranslatedIndexData &indexInfo); GLenum applyVertexBuffer(const TranslatedIndexData &indexInfo);
GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
void applyShaders(); void applyShaders();
void applyTextures(); void applyTextures();
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "libGLESv2/geometry/VertexDataManager.h" #include "libGLESv2/geometry/VertexDataManager.h"
#include <limits>
#include "common/debug.h" #include "common/debug.h"
#include "libGLESv2/Buffer.h" #include "libGLESv2/Buffer.h"
...@@ -132,24 +134,44 @@ GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count, ...@@ -132,24 +134,44 @@ GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
translated[i].stride = formatConverter.outputVertexSize; translated[i].stride = formatConverter.outputVertexSize;
translated[i].buffer = mStreamBuffer; translated[i].buffer = mStreamBuffer;
size_t inputStride = interpretGlStride(attribs[i]);
size_t elementSize = typeSize(attribs[i].mType) * attribs[i].mSize;
void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset); void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset);
const void *input; const void *input;
if (attribs[i].mBoundBuffer) if (attribs[i].mBoundBuffer)
{ {
input = mContext->getBuffer(attribs[i].mBoundBuffer)->data(); Buffer *buffer = mContext->getBuffer(attribs[i].mBoundBuffer);
input = static_cast<const char*>(input) + reinterpret_cast<size_t>(attribs[i].mPointer);
size_t offset = reinterpret_cast<size_t>(attribs[i].mPointer);
// Before we calculate the required size below, make sure it can be computed without integer overflow.
if (std::numeric_limits<std::size_t>::max() - start < static_cast<std::size_t>(count)
|| std::numeric_limits<std::size_t>::max() / inputStride < static_cast<std::size_t>(start + count - 1) // it's a prerequisite that count >= 1, so start+count-1 >= 0.
|| std::numeric_limits<std::size_t>::max() - offset < inputStride * (start + count - 1)
|| std::numeric_limits<std::size_t>::max() - elementSize < offset + inputStride * (start + count - 1) + elementSize)
{
mStreamBuffer->unmap();
return GL_INVALID_OPERATION;
}
if (offset + inputStride * (start + count - 1) + elementSize > buffer->size())
{
mStreamBuffer->unmap();
return GL_INVALID_OPERATION;
}
input = static_cast<const char*>(buffer->data()) + offset;
} }
else else
{ {
input = attribs[i].mPointer; input = attribs[i].mPointer;
} }
size_t inputStride = interpretGlStride(attribs[i]);
input = static_cast<const char*>(input) + inputStride * start; input = static_cast<const char*>(input) + inputStride * start;
if (formatConverter.identity && inputStride == typeSize(attribs[i].mType) * attribs[i].mSize) if (formatConverter.identity && inputStride == elementSize)
{ {
memcpy(output, input, count * inputStride); memcpy(output, input, count * inputStride);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment