Bug 747619 - fix uniform setter validation: allow partial uniform array updates - r=jgilbert

This commit is contained in:
Benoit Jacob 2012-05-03 15:57:25 -04:00
parent 843317626a
commit 236dd8e7f5

View File

@ -4164,7 +4164,7 @@ GetFloat32Array(JSContext* aCx, const JS::Value& aValue)
return ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info); \ return ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info); \
GLint location = location_object->Location(); GLint location = location_object->Location();
#define SIMPLE_ARRAY_METHOD_UNIFORM(name, cnt, arrayType, ptrType) \ #define SIMPLE_ARRAY_METHOD_UNIFORM(name, expectedElemSize, arrayType, ptrType) \
NS_IMETHODIMP \ NS_IMETHODIMP \
WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue, \ WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue, \
JSContext* aCx) \ JSContext* aCx) \
@ -4180,40 +4180,39 @@ WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue,
\ \
nsIWebGLUniformLocation* ploc = aLocation; \ nsIWebGLUniformLocation* ploc = aLocation; \
OBTAIN_UNIFORM_LOCATION(#name ": location") \ OBTAIN_UNIFORM_LOCATION(#name ": location") \
int elementSize = location_object->ElementSize(); \ int uniformElemSize = location_object->ElementSize(); \
if (cnt != elementSize) { \ if (expectedElemSize != uniformElemSize) { \
return ErrorInvalidOperation( \ return ErrorInvalidOperation( \
#name ": this function expected a uniform of element size %d," \ #name ": this function expected a uniform of element size %d," \
" got a uniform of element size %d", \ " got a uniform of element size %d", \
cnt, \ expectedElemSize, \
elementSize); \ uniformElemSize); \
} \ } \
PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx); \ PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx); \
const WebGLUniformInfo& info = location_object->Info(); \ const WebGLUniformInfo& info = location_object->Info(); \
PRUint32 expectedArrayLength = cnt * info.arraySize; \ if (arrayLength == 0 || \
if (arrayLength < expectedArrayLength || \ arrayLength % expectedElemSize) \
(arrayLength % cnt)) \
{ \ { \
return ErrorInvalidValue("%s: expected an array of length a multiple of" \ return ErrorInvalidValue("%s: expected an array of length a multiple of" \
" %d and at least %d, got an array of length %d", \ " %d, got an array of length %d", \
#name, \ #name, \
cnt, \ expectedElemSize, \
expectedArrayLength, \
arrayLength); \ arrayLength); \
} \ } \
if (!info.isArray && \ if (!info.isArray && \
arrayLength > expectedArrayLength) { \ arrayLength != expectedElemSize) { \
return ErrorInvalidOperation("%s: expected an array of length exactly %d" \ return ErrorInvalidOperation("%s: expected an array of length exactly %d" \
" (since this uniform is not an array uniform)," \ " (since this uniform is not an array uniform)," \
" got an array of length %d", \ " got an array of length %d", \
#name, \ #name, \
expectedArrayLength, \ expectedElemSize, \
arrayLength); \ arrayLength); \
} \ } \
\ \
MakeContextCurrent(); \ MakeContextCurrent(); \
gl->f##name(location, info.arraySize, \ PRUint32 numElementsToUpload = NS_MIN(info.arraySize, arrayLength/expectedElemSize); \
static_cast<ptrType*>(JS_GetArrayBufferViewData(wa, aCx))); \ gl->f##name(location, numElementsToUpload, \
static_cast<ptrType*>(JS_GetArrayBufferViewData(wa, aCx))); \
return NS_OK; \ return NS_OK; \
} }
@ -4222,6 +4221,7 @@ NS_IMETHODIMP
WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose, \ WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose, \
const JS::Value& aValue, JSContext* aCx) \ const JS::Value& aValue, JSContext* aCx) \
{ \ { \
int expectedElemSize = (dim)*(dim); \
JSObject* wa = GetFloat32Array(aCx, aValue); \ JSObject* wa = GetFloat32Array(aCx, aValue); \
if (!wa) { \ if (!wa) { \
return NS_ERROR_FAILURE; \ return NS_ERROR_FAILURE; \
@ -4236,34 +4236,32 @@ WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,
if (!wa || !JS_IsFloat32Array(wa, aCx)) { \ if (!wa || !JS_IsFloat32Array(wa, aCx)) { \
return ErrorInvalidValue(#name ": array must be of Float32 type"); \ return ErrorInvalidValue(#name ": array must be of Float32 type"); \
} \ } \
int elementSize = location_object->ElementSize(); \ int uniformElemSize = location_object->ElementSize(); \
if (dim*dim != elementSize) { \ if (expectedElemSize != uniformElemSize) { \
return ErrorInvalidOperation( \ return ErrorInvalidOperation( \
#name ": this function expected a uniform of element size %d," \ #name ": this function expected a uniform of element size %d," \
" got a uniform of element size %d", \ " got a uniform of element size %d", \
dim*dim, \ expectedElemSize, \
elementSize); \ uniformElemSize); \
} \ } \
PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx); \ PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx); \
const WebGLUniformInfo& info = location_object->Info(); \ const WebGLUniformInfo& info = location_object->Info(); \
PRUint32 expectedArrayLength = dim * dim * info.arraySize; \ if (arrayLength == 0 || \
if (arrayLength < expectedArrayLength || \ arrayLength % expectedElemSize) \
(arrayLength % (dim*dim))) \
{ \ { \
return ErrorInvalidValue("%s: expected an array of length a multiple of" \ return ErrorInvalidValue("%s: expected an array of length a multiple of" \
" %d and at least %d, got an array of length %d", \ " %d, got an array of length %d", \
#name, \ #name, \
dim*dim, \ expectedElemSize, \
expectedArrayLength, \
arrayLength); \ arrayLength); \
} \ } \
if (!info.isArray && \ if (!info.isArray && \
arrayLength > expectedArrayLength) { \ arrayLength != expectedElemSize) { \
return ErrorInvalidOperation("%s: expected an array of length exactly %d" \ return ErrorInvalidOperation("%s: expected an array of length exactly %d" \
" (since this uniform is not an array uniform)," \ " (since this uniform is not an array uniform)," \
" got an array of length %d", \ " got an array of length %d", \
#name, \ #name, \
expectedArrayLength, \ expectedElemSize, \
arrayLength); \ arrayLength); \
} \ } \
if (aTranspose) { \ if (aTranspose) { \
@ -4272,7 +4270,8 @@ WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,
} \ } \
\ \
MakeContextCurrent(); \ MakeContextCurrent(); \
gl->f##name(location, info.arraySize, false, \ PRUint32 numElementsToUpload = NS_MIN(info.arraySize, arrayLength/(expectedElemSize)); \
gl->f##name(location, numElementsToUpload, false, \
static_cast<WebGLfloat*>(JS_GetArrayBufferViewData(wa, aCx))); \ static_cast<WebGLfloat*>(JS_GetArrayBufferViewData(wa, aCx))); \
return NS_OK; \ return NS_OK; \
} }