diff options
author | Greg Daniel <egdaniel@google.com> | 2018-06-07 13:15:10 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-06-07 17:38:01 +0000 |
commit | d5b4593024544c3405615066aa5b4f94352eb3cb (patch) | |
tree | 9e6b507ecf6674d2905caf3636eb43b8731d5285 /src/gpu | |
parent | 8345aa6302c7ca25a4b9c2df913e83ef79220ab7 (diff) |
Add checks to make sure we don't overflow 32 bit int in GPU path renderers.
Bug: chromium:848716
Change-Id: I5b8fe036c666a1f379c4125115b2cec0295711b3
Reviewed-on: https://skia-review.googlesource.com/132268
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrTessellator.cpp | 20 | ||||
-rw-r--r-- | src/gpu/ops/GrAAConvexPathRenderer.cpp | 22 | ||||
-rw-r--r-- | src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp | 30 | ||||
-rw-r--r-- | src/gpu/ops/GrSmallPathRenderer.cpp | 6 |
4 files changed, 52 insertions, 26 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp index 79f5765ee4..9369d70c30 100644 --- a/src/gpu/GrTessellator.cpp +++ b/src/gpu/GrTessellator.cpp @@ -2116,8 +2116,8 @@ int get_contour_count(const SkPath& path, SkScalar tolerance) { return contourCnt; } -int count_points(Poly* polys, SkPath::FillType fillType) { - int count = 0; +int64_t count_points(Poly* polys, SkPath::FillType fillType) { + int64_t count = 0; for (Poly* poly = polys; poly; poly = poly->fNext) { if (apply_fill_type(fillType, poly) && poly->fCount >= 3) { count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3); @@ -2126,8 +2126,8 @@ int count_points(Poly* polys, SkPath::FillType fillType) { return count; } -int count_outer_mesh_points(const VertexList& outerMesh) { - int count = 0; +int64_t count_outer_mesh_points(const VertexList& outerMesh) { + int64_t count = 0; for (Vertex* v = outerMesh.fHead; v; v = v->fNext) { for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { count += TESSELLATOR_WIREFRAME ? 12 : 6; @@ -2169,13 +2169,14 @@ int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBo Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, antialias, isLinear, &outerMesh); SkPath::FillType fillType = antialias ? SkPath::kWinding_FillType : path.getFillType(); - int count = count_points(polys, fillType); + int64_t count64 = count_points(polys, fillType); if (antialias) { - count += count_outer_mesh_points(outerMesh); + count64 += count_outer_mesh_points(outerMesh); } - if (0 == count) { + if (0 == count64 || count64 > SK_MaxS32) { return 0; } + int count = count64; void* verts = vertexAllocator->lock(count); if (!verts) { @@ -2209,11 +2210,12 @@ int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBou Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, false, &isLinear, nullptr); SkPath::FillType fillType = path.getFillType(); - int count = count_points(polys, fillType); - if (0 == count) { + int64_t count64 = count_points(polys, fillType); + if (0 == count64 || count64 > SK_MaxS32) { *verts = nullptr; return 0; } + int count = count64; *verts = new GrTessellator::WindingVertex[count]; GrTessellator::WindingVertex* vertsEnd = *verts; diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp index a1d7392de0..d1fbbc4e7b 100644 --- a/src/gpu/ops/GrAAConvexPathRenderer.cpp +++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp @@ -22,6 +22,7 @@ #include "SkPointPriv.h" #include "SkString.h" #include "SkTraceEvent.h" +#include "SkTypes.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLGeometryProcessor.h" #include "glsl/GrGLSLProgramDataManager.h" @@ -132,8 +133,8 @@ static bool compute_vectors(SegmentArray* segments, normSide = SkPointPriv::kLeft_Side; } - *vCount = 0; - *iCount = 0; + int64_t vCount64 = 0; + int64_t iCount64 = 0; // compute normals at all points for (int a = 0; a < count; ++a) { Segment& sega = (*segments)[a]; @@ -149,11 +150,11 @@ static bool compute_vectors(SegmentArray* segments, prevPt = &segb.fPts[p]; } if (Segment::kLine == segb.fType) { - *vCount += 5; - *iCount += 9; + vCount64 += 5; + iCount64 += 9; } else { - *vCount += 6; - *iCount += 12; + vCount64 += 6; + iCount64 += 12; } } @@ -166,9 +167,14 @@ static bool compute_vectors(SegmentArray* segments, segb.fMid = segb.fNorms[0] + sega.endNorm(); segb.fMid.normalize(); // corner wedges - *vCount += 4; - *iCount += 6; + vCount64 += 4; + iCount64 += 6; } + if (vCount64 > SK_MaxS32 || iCount64 > SK_MaxS32) { + return false; + } + *vCount = vCount64; + *iCount = iCount64; return true; } diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp index 2176e0914b..2c1ea50fc3 100644 --- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp +++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp @@ -255,10 +255,10 @@ private: int instanceCount = fPaths.count(); - int vertexCount = 0; - int indexCount = 0; - int maxVertices = DEFAULT_BUFFER_SIZE; - int maxIndices = DEFAULT_BUFFER_SIZE; + int64_t vertexCount = 0; + int64_t indexCount = 0; + int64_t maxVertices = DEFAULT_BUFFER_SIZE; + int64_t maxIndices = DEFAULT_BUFFER_SIZE; uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride); uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t)); for (int i = 0; i < instanceCount; i++) { @@ -270,8 +270,8 @@ private: continue; } - int currentIndices = tess.numIndices(); - if (indexCount + currentIndices > static_cast<int>(UINT16_MAX)) { + int currentVertices = tess.numPts(); + if (vertexCount + currentVertices > static_cast<int>(UINT16_MAX)) { // if we added the current instance, we would overflow the indices we can store in a // uint16_t. Draw what we've got so far and reset. this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, @@ -279,13 +279,23 @@ private: vertexCount = 0; indexCount = 0; } - int currentVertices = tess.numPts(); if (vertexCount + currentVertices > maxVertices) { maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2); + if (maxVertices * vertexStride > SK_MaxS32) { + sk_free(vertices); + sk_free(indices); + return; + } vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride); } + int currentIndices = tess.numIndices(); if (indexCount + currentIndices > maxIndices) { maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2); + if (maxIndices * sizeof(uint16_t) > SK_MaxS32) { + sk_free(vertices); + sk_free(indices); + return; + } indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t)); } @@ -295,8 +305,10 @@ private: vertexCount += currentVertices; indexCount += currentIndices; } - this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, - indices); + if (vertexCount <= SK_MaxS32 && indexCount <= SK_MaxS32) { + this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, + indices); + } sk_free(vertices); sk_free(indices); } diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp index cbf1f68ac4..2ad23cbeaf 100644 --- a/src/gpu/ops/GrSmallPathRenderer.cpp +++ b/src/gpu/ops/GrSmallPathRenderer.cpp @@ -351,6 +351,12 @@ private: SkASSERT(vertexStride == sizeof(SkPoint) + sizeof(GrColor) + 2*sizeof(uint16_t)); const GrBuffer* vertexBuffer; + + // We need to make sure we don't overflow a 32 bit int when we request space in the + // makeVertexSpace call below. + if (instanceCount > SK_MaxS32 / kVerticesPerQuad) { + return; + } void* vertices = target->makeVertexSpace(vertexStride, kVerticesPerQuad * instanceCount, &vertexBuffer, |