Changeset 226814 in webkit


Ignore:
Timestamp:
Jan 11, 2018 3:57:52 PM (6 years ago)
Author:
dino@apple.com
Message:

[WebGL] Simulated vertexAttrib0 can sometimes cause OUT_OF_MEMORY errors
https://bugs.webkit.org/show_bug.cgi?id=181558
<rdar://problem/36189833>

Reviewed by Eric Carlson.

Source/WebCore:

Very large element indices in the ELEMENT_ARRAY_BUFFER meant that
our simulated vertexAttrib0 buffer might be too large. We need
to check for out-of-memory, but we can also detect some of the issues
earlier in our validation code. Additionally, make sure that we don't
accidentally cast an unsigned to a signed.

Test: fast/canvas/webgl/simulated-vertexAttrib0-invalid-indicies.html

  • html/canvas/WebGL2RenderingContext.cpp:

(WebCore::WebGL2RenderingContext::validateIndexArrayConservative): Update validation
code to look for overflow, rather than relying on looking for sign changes.

  • html/canvas/WebGLRenderingContext.cpp:

(WebCore::WebGLRenderingContext::validateIndexArrayConservative): Ditto.

  • html/canvas/WebGLRenderingContextBase.cpp:

(WebCore::WebGLRenderingContextBase::validateIndexArrayPrecise):
(WebCore::WebGLRenderingContextBase::drawArrays): Check that we were able to simulate.
(WebCore::WebGLRenderingContextBase::drawElements):
(WebCore::WebGLRenderingContextBase::validateSimulatedVertexAttrib0): Update validation code, and
use GC3Duint, since that's what the indicies are.
(WebCore::WebGLRenderingContextBase::simulateVertexAttrib0): Ditto.
(WebCore::WebGLRenderingContextBase::drawArraysInstanced): Check that we were able to simulate.
(WebCore::WebGLRenderingContextBase::drawElementsInstanced):

  • html/canvas/WebGLRenderingContextBase.h:

LayoutTests:

  • fast/canvas/webgl/simulated-vertexAttrib0-invalid-indicies-expected.txt: Added.
  • fast/canvas/webgl/simulated-vertexAttrib0-invalid-indicies.html: Added.
Location:
trunk
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r226813 r226814  
     12018-01-11  Dean Jackson  <dino@apple.com>
     2
     3        [WebGL] Simulated vertexAttrib0 can sometimes cause OUT_OF_MEMORY errors
     4        https://bugs.webkit.org/show_bug.cgi?id=181558
     5        <rdar://problem/36189833>
     6
     7        Reviewed by Eric Carlson.
     8
     9        * fast/canvas/webgl/simulated-vertexAttrib0-invalid-indicies-expected.txt: Added.
     10        * fast/canvas/webgl/simulated-vertexAttrib0-invalid-indicies.html: Added.
     11
    1122018-01-11  Chris Dumez  <cdumez@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r226813 r226814  
     12018-01-11  Dean Jackson  <dino@apple.com>
     2
     3        [WebGL] Simulated vertexAttrib0 can sometimes cause OUT_OF_MEMORY errors
     4        https://bugs.webkit.org/show_bug.cgi?id=181558
     5        <rdar://problem/36189833>
     6
     7        Reviewed by Eric Carlson.
     8
     9        Very large element indices in the ELEMENT_ARRAY_BUFFER meant that
     10        our simulated vertexAttrib0 buffer might be too large. We need
     11        to check for out-of-memory, but we can also detect some of the issues
     12        earlier in our validation code. Additionally, make sure that we don't
     13        accidentally cast an unsigned to a signed.
     14
     15        Test: fast/canvas/webgl/simulated-vertexAttrib0-invalid-indicies.html
     16
     17        * html/canvas/WebGL2RenderingContext.cpp:
     18        (WebCore::WebGL2RenderingContext::validateIndexArrayConservative): Update validation
     19        code to look for overflow, rather than relying on looking for sign changes.
     20        * html/canvas/WebGLRenderingContext.cpp:
     21        (WebCore::WebGLRenderingContext::validateIndexArrayConservative): Ditto.
     22        * html/canvas/WebGLRenderingContextBase.cpp:
     23        (WebCore::WebGLRenderingContextBase::validateIndexArrayPrecise):
     24        (WebCore::WebGLRenderingContextBase::drawArrays): Check that we were able to simulate.
     25        (WebCore::WebGLRenderingContextBase::drawElements):
     26        (WebCore::WebGLRenderingContextBase::validateSimulatedVertexAttrib0): Update validation code, and
     27        use GC3Duint, since that's what the indicies are.
     28        (WebCore::WebGLRenderingContextBase::simulateVertexAttrib0): Ditto.
     29        (WebCore::WebGLRenderingContextBase::drawArraysInstanced): Check that we were able to simulate.
     30        (WebCore::WebGLRenderingContextBase::drawElementsInstanced):
     31        * html/canvas/WebGLRenderingContextBase.h:
     32
    1332018-01-11  Chris Dumez  <cdumez@apple.com>
    234
  • trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp

    r226439 r226814  
    18231823    // The number of required elements is one more than the maximum
    18241824    // index that will be accessed.
    1825     numElementsRequired = maxIndex.value() + 1;
    1826 
    1827     // Check for overflow.
    1828     return numElementsRequired > 0;
     1825    Checked<unsigned, RecordOverflow> checkedNumElementsRequired = Checked<unsigned>(maxIndex.value());
     1826    checkedNumElementsRequired += 1;
     1827    if (checkedNumElementsRequired.hasOverflowed())
     1828        return false;
     1829    numElementsRequired = checkedNumElementsRequired.unsafeGet();
     1830    return true;
    18291831}
    18301832
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp

    r226439 r226814  
    721721    // The number of required elements is one more than the maximum
    722722    // index that will be accessed.
    723     numElementsRequired = maxIndex.value() + 1;
    724 
    725     // Check for overflow.
    726     return numElementsRequired > 0;
     723    Checked<unsigned, RecordOverflow> checkedNumElementsRequired = Checked<unsigned>(maxIndex.value());
     724    checkedNumElementsRequired += 1;
     725    if (checkedNumElementsRequired.hasOverflowed())
     726        return false;
     727    numElementsRequired = checkedNumElementsRequired.unsafeGet();
     728    return true;
    727729}
    728730
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp

    r226490 r226814  
    18931893
    18941894    // Then set the last index in the index array and make sure it is valid.
    1895     numElementsRequired = lastIndex + 1;
    1896     return numElementsRequired > 0;
     1895    Checked<unsigned, RecordOverflow> checkedNumElementsRequired = Checked<unsigned>(lastIndex);
     1896    checkedNumElementsRequired += 1;
     1897    if (checkedNumElementsRequired.hasOverflowed())
     1898        return false;
     1899    numElementsRequired = checkedNumElementsRequired.unsafeGet();
     1900    return true;
    18971901}
    18981902
     
    21162120
    21172121    bool vertexAttrib0Simulated = false;
    2118     if (!isGLES2Compliant())
    2119         vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
     2122    if (!isGLES2Compliant()) {
     2123        auto simulateVertexAttrib0Status = simulateVertexAttrib0(first + count - 1);
     2124        if (!simulateVertexAttrib0Status) {
     2125            // We were unable to simulate the attribute buffer.
     2126            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawArrays", "unable to simulate vertexAttrib0 array");
     2127            return;
     2128        }
     2129        vertexAttrib0Simulated = simulateVertexAttrib0Status.value();
     2130    }
    21202131    bool usesFallbackTexture = false;
    21212132    if (!isGLES2NPOTStrict())
     
    21462157        if (!numElements)
    21472158            validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
    2148         vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
     2159        auto simulateVertexAttrib0Status = simulateVertexAttrib0(numElements);
     2160        if (!simulateVertexAttrib0Status) {
     2161            // We were unable to simulate the attribute buffer.
     2162            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "unable to simulate vertexAttrib0 array");
     2163            return;
     2164        }
     2165        vertexAttrib0Simulated = simulateVertexAttrib0Status.value();
    21492166    }
    21502167
     
    56835700}
    56845701
    5685 bool WebGLRenderingContextBase::validateSimulatedVertexAttrib0(GC3Dsizei numVertex)
    5686 {
    5687     if (numVertex < 0)
    5688         return false;
    5689 
     5702bool WebGLRenderingContextBase::validateSimulatedVertexAttrib0(GC3Duint numVertex)
     5703{
    56905704    if (!m_currentProgram)
    56915705        return true;
     
    56995713        return true;
    57005714
    5701     Checked<GC3Dsizei, RecordOverflow> bufferSize(numVertex);
     5715    Checked<GC3Duint, RecordOverflow> bufferSize(numVertex);
    57025716    bufferSize += 1;
    5703     bufferSize *= Checked<GC3Dsizei>(4);
     5717    bufferSize *= Checked<GC3Duint>(4);
     5718    if (bufferSize.hasOverflowed())
     5719        return false;
    57045720    Checked<GC3Dsizeiptr, RecordOverflow> bufferDataSize(bufferSize);
    57055721    bufferDataSize *= Checked<GC3Dsizeiptr>(sizeof(GC3Dfloat));
    5706     return !bufferDataSize.hasOverflowed();
    5707 }
    5708 
    5709 bool WebGLRenderingContextBase::simulateVertexAttrib0(GC3Dsizei numVertex)
     5722    return !bufferDataSize.hasOverflowed() && bufferDataSize.unsafeGet() > 0;
     5723}
     5724
     5725std::optional<bool> WebGLRenderingContextBase::simulateVertexAttrib0(GC3Duint numVertex)
    57105726{
    57115727    if (!m_currentProgram)
     
    57235739    m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
    57245740
    5725     Checked<GC3Dsizei> bufferSize(numVertex);
     5741    Checked<GC3Duint> bufferSize(numVertex);
    57265742    bufferSize += 1;
    5727     bufferSize *= Checked<GC3Dsizei>(4);
     5743    bufferSize *= Checked<GC3Duint>(4);
    57285744
    57295745    Checked<GC3Dsizeiptr> bufferDataSize(bufferSize);
     
    57315747
    57325748    if (bufferDataSize.unsafeGet() > m_vertexAttrib0BufferSize) {
     5749        m_context->moveErrorsToSyntheticErrorList();
    57335750        m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize.unsafeGet(), 0, GraphicsContext3D::DYNAMIC_DRAW);
     5751        if (m_context->getError() != GraphicsContext3D::NO_ERROR) {
     5752            // We were unable to create a buffer.
     5753            m_vertexAttrib0UsedBefore = false;
     5754            return std::nullopt;
     5755        }
    57345756        m_vertexAttrib0BufferSize = bufferDataSize.unsafeGet();
    57355757        m_forceAttrib0BufferRefill = true;
     
    57465768
    57475769        auto bufferData = std::make_unique<GC3Dfloat[]>(bufferSize.unsafeGet());
    5748         for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
     5770        for (GC3Duint ii = 0; ii < numVertex + 1; ++ii) {
    57495771            bufferData[ii * 4] = attribValue.value[0];
    57505772            bufferData[ii * 4 + 1] = attribValue.value[1];
     
    60496071
    60506072    bool vertexAttrib0Simulated = false;
    6051     if (!isGLES2Compliant())
    6052         vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
     6073    if (!isGLES2Compliant()) {
     6074        auto simulateVertexAttrib0Status = simulateVertexAttrib0(first + count - 1);
     6075        if (!simulateVertexAttrib0Status) {
     6076            // We were unable to simulate the attribute buffer.
     6077            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawArraysInstanced", "unable to simulate vertexAttrib0 array");
     6078            return;
     6079        }
     6080        vertexAttrib0Simulated = simulateVertexAttrib0Status.value();
     6081    }
    60536082    if (!isGLES2NPOTStrict())
    60546083        checkTextureCompleteness("drawArraysInstanced", true);
     
    60806109        if (!numElements)
    60816110            validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
    6082         vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
     6111        auto simulateVertexAttrib0Status = simulateVertexAttrib0(numElements);
     6112        if (!simulateVertexAttrib0Status) {
     6113            // We were unable to simulate the attribute buffer.
     6114            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawArraysInstanced", "unable to simulate vertexAttrib0 array");
     6115            return;
     6116        }
     6117        vertexAttrib0Simulated = simulateVertexAttrib0Status.value();
    60836118    }
    60846119    if (!isGLES2NPOTStrict())
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h

    r226490 r226814  
    793793    // Helpers for simulating vertexAttrib0.
    794794    void initVertexAttrib0();
    795     bool simulateVertexAttrib0(GC3Dsizei numVertex);
    796     bool validateSimulatedVertexAttrib0(GC3Dsizei numVertex);
     795    std::optional<bool> simulateVertexAttrib0(GC3Duint numVertex);
     796    bool validateSimulatedVertexAttrib0(GC3Duint numVertex);
    797797    void restoreStatesAfterVertexAttrib0Simulation();
    798798
Note: See TracChangeset for help on using the changeset viewer.