mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1333858 - Intersect should be fallible on overflow. - r=daoshengmu
MozReview-Commit-ID: 6lmIKKyXXah
This commit is contained in:
parent
f994cca810
commit
5108749361
@ -2225,25 +2225,47 @@ ScopedLazyBind::UnwrapImpl()
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
void
|
||||
Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
|
||||
uint32_t* const out_intStartInSrc, uint32_t* const out_intStartInDst,
|
||||
uint32_t* const out_intSize)
|
||||
bool
|
||||
Intersect(const int32_t srcSize, const int32_t read0, const int32_t readSize,
|
||||
int32_t* const out_intRead0, int32_t* const out_intWrite0,
|
||||
int32_t* const out_intSize)
|
||||
{
|
||||
// Only >0 if dstStartInSrc is >0:
|
||||
// 0 3 // src coords
|
||||
// | [========] // dst box
|
||||
// ^--^
|
||||
*out_intStartInSrc = std::max<int32_t>(0, dstStartInSrc);
|
||||
MOZ_ASSERT(srcSize >= 0);
|
||||
MOZ_ASSERT(readSize >= 0);
|
||||
const auto read1 = int64_t(read0) + readSize;
|
||||
|
||||
// Only >0 if dstStartInSrc is <0:
|
||||
//-6 0 // src coords
|
||||
// [=====|==] // dst box
|
||||
// ^-----^
|
||||
*out_intStartInDst = std::max<int32_t>(0, 0 - dstStartInSrc);
|
||||
int32_t intRead0 = read0; // Clearly doesn't need validation.
|
||||
int64_t intWrite0 = 0;
|
||||
int64_t intSize = readSize;
|
||||
|
||||
int32_t intEndInSrc = std::min<int32_t>(srcSize, dstStartInSrc + dstSize);
|
||||
*out_intSize = std::max<int32_t>(0, intEndInSrc - *out_intStartInSrc);
|
||||
if (read1 <= 0 || read0 >= srcSize) {
|
||||
// Disjoint ranges.
|
||||
intSize = 0;
|
||||
} else {
|
||||
if (read0 < 0) {
|
||||
const auto diff = int64_t(0) - read0;
|
||||
MOZ_ASSERT(diff >= 0);
|
||||
intRead0 = 0;
|
||||
intWrite0 = diff;
|
||||
intSize -= diff;
|
||||
}
|
||||
if (read1 > srcSize) {
|
||||
const auto diff = int64_t(read1) - srcSize;
|
||||
MOZ_ASSERT(diff >= 0);
|
||||
intSize -= diff;
|
||||
}
|
||||
|
||||
if (!CheckedInt<int32_t>(intWrite0).isValid() ||
|
||||
!CheckedInt<int32_t>(intSize).isValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*out_intRead0 = intRead0;
|
||||
*out_intWrite0 = intWrite0;
|
||||
*out_intSize = intSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2164,10 +2164,9 @@ private:
|
||||
|
||||
////
|
||||
|
||||
void
|
||||
Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
|
||||
uint32_t* const out_intStartInSrc, uint32_t* const out_intStartInDst,
|
||||
uint32_t* const out_intSize);
|
||||
bool
|
||||
Intersect(int32_t srcSize, int32_t read0, int32_t readSize, int32_t* out_intRead0,
|
||||
int32_t* out_intWrite0, int32_t* out_intSize);
|
||||
|
||||
////
|
||||
|
||||
|
@ -1556,18 +1556,32 @@ WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeig
|
||||
return;
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
int32_t readX, readY;
|
||||
int32_t writeX, writeY;
|
||||
int32_t rwWidth, rwHeight;
|
||||
if (!Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth) ||
|
||||
!Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight))
|
||||
{
|
||||
ErrorOutOfMemory("readPixels: Bad subrect selection.");
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Now that the errors are out of the way, on to actually reading!
|
||||
|
||||
OnBeforeReadCall();
|
||||
|
||||
uint32_t readX, readY;
|
||||
uint32_t writeX, writeY;
|
||||
uint32_t rwWidth, rwHeight;
|
||||
Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth);
|
||||
Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight);
|
||||
if (!rwWidth || !rwHeight) {
|
||||
// Disjoint rects, so we're done already.
|
||||
DummyReadFramebufferOperation("readPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height)) {
|
||||
if (uint32_t(rwWidth) == width &&
|
||||
uint32_t(rwHeight) == height)
|
||||
{
|
||||
DoReadPixelsAndConvert(srcFormat->format, x, y, width, height, packFormat,
|
||||
packType, dest, dataLen, rowStride);
|
||||
return;
|
||||
@ -1586,12 +1600,6 @@ WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeig
|
||||
////////////////////////////////////
|
||||
// Read only the in-bounds pixels.
|
||||
|
||||
if (!rwWidth || !rwHeight) {
|
||||
// There aren't any, so we're 'done'.
|
||||
DummyReadFramebufferOperation("readPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsWebGL2()) {
|
||||
if (!mPixelStore_PackRowLength) {
|
||||
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH,
|
||||
@ -1611,7 +1619,7 @@ WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeig
|
||||
|
||||
uint8_t* row = (uint8_t*)dest + writeX * bytesPerPixel;
|
||||
row += writeY * rowStride;
|
||||
for (uint32_t j = 0; j < rwHeight; j++) {
|
||||
for (uint32_t j = 0; j < uint32_t(rwHeight); j++) {
|
||||
DoReadPixelsAndConvert(srcFormat->format, readX, readY+j, rwWidth, 1,
|
||||
packFormat, packType, row, dataLen, rowStride);
|
||||
row += rowStride;
|
||||
|
@ -2011,11 +2011,15 @@ DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
|
||||
|
||||
////
|
||||
|
||||
uint32_t readX, readY;
|
||||
uint32_t writeX, writeY;
|
||||
uint32_t rwWidth, rwHeight;
|
||||
Intersect(srcTotalWidth, xWithinSrc, dstWidth, &readX, &writeX, &rwWidth);
|
||||
Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight);
|
||||
int32_t readX, readY;
|
||||
int32_t writeX, writeY;
|
||||
int32_t rwWidth, rwHeight;
|
||||
if (!Intersect(srcTotalWidth, xWithinSrc, dstWidth, &readX, &writeX, &rwWidth) ||
|
||||
!Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight))
|
||||
{
|
||||
webgl->ErrorOutOfMemory("%s: Bad subrect selection.", funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
writeX += xOffset;
|
||||
writeY += yOffset;
|
||||
@ -2028,7 +2032,7 @@ DoCopyTexOrSubImage(WebGLContext* webgl, const char* funcName, bool isSubImage,
|
||||
if (!isSubImage) {
|
||||
UniqueBuffer buffer;
|
||||
|
||||
if (rwWidth != dstWidth || rwHeight != dstHeight) {
|
||||
if (uint32_t(rwWidth) != dstWidth || uint32_t(rwHeight) != dstHeight) {
|
||||
const auto& pi = idealUnpack->ToPacking();
|
||||
CheckedUint32 byteCount = BytesPerPixel(pi);
|
||||
byteCount *= dstWidth;
|
||||
|
Loading…
Reference in New Issue
Block a user