From 538a2fb4741da9ad1b1b7ea4e233294cae834a08 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Tue, 21 Jul 2020 01:22:13 +0200 Subject: [PATCH] prevent overflow of index addressing --- src/vkvg_context.c | 49 +++++++++++++++++++++++++++---------- src/vkvg_context_internal.c | 27 ++++++++++++++------ src/vkvg_context_internal.h | 9 ++++++- 3 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/vkvg_context.c b/src/vkvg_context.c index d7214c3..fa2ff2b 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -581,12 +581,12 @@ void vkvg_clip_preserve (VkvgContext ctx){ LOG(VKVG_LOG_INFO, "CLIP: ctx = %p; path cpt = %d;\n", ctx, ctx->pathPtr / 2); + _ensure_renderpass_is_started(ctx); + if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD){ - _ensure_renderpass_is_started(ctx); _poly_fill (ctx); CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineClipping); }else{ - _ensure_renderpass_is_started(ctx); CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineClipping); CmdSetStencilReference (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); @@ -613,6 +613,7 @@ void vkvg_fill_preserve (VkvgContext ctx){ if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD){ _flush_undrawn_vertices(ctx); + _poly_fill (ctx); _bind_draw_pipeline (ctx); CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); @@ -621,11 +622,13 @@ void vkvg_fill_preserve (VkvgContext ctx){ return; } + if (ctx->vertCount - ctx->curVertOffset + ctx->pointCount > VKVG_IBO_MAX) + _flush_undrawn_vertices(ctx);//limit draw call to addressable vx with choosen index type + if (ctx->pattern)//if not solid color, source img of gradient has to be bound _ensure_renderpass_is_started(ctx); _fill_ec(ctx); } - void _draw_stoke_cap (VkvgContext ctx, float hw, vec2 p0, vec2 n, bool isStart) { Vertex v = {{0},ctx->curColor}; @@ -733,16 +736,10 @@ void _draw_segment (VkvgContext ctx, float hw, bool isCurve) { _build_vb_step (ctx, hw, ctx->points[iL], ctx->points[curPathPointIdx], ctx->points[iR], isCurve); iL = curPathPointIdx++; } -void vkvg_stroke_preserve (VkvgContext ctx) -{ - if (ctx->pathPtr == 0 && _current_path_is_empty(ctx))//nothing to stroke - return; - _finish_path(ctx); - LOG(VKVG_LOG_INFO, "STROKE: ctx = %p; path cpt = %d;\n", ctx, ctx->pathPtr / 2); - - float hw = ctx->lineWidth / 2.0f; +bool _process_stroke (VkvgContext ctx) { curPathPointIdx = lastPathPointIdx = ptrPath = iL = iR = 0; + float hw = ctx->lineWidth / 2.0f; while (ptrPath < ctx->pathPtr){ uint32_t ptrSegment = 0, lastSegmentPointIdx = 0; @@ -771,7 +768,7 @@ void vkvg_stroke_preserve (VkvgContext ctx) totDashLength+=ctx->dashes[i]; if (totDashLength == 0){ ctx->status = VKVG_STATUS_INVALID_DASH; - return; + return true; } /*if (ctx->dashOffset == 0) curDashOffset = 0; @@ -842,6 +839,9 @@ void vkvg_stroke_preserve (VkvgContext ctx) }else _draw_stoke_cap (ctx, hw, ctx->points[curPathPointIdx], vec2_line_norm(ctx->points[curPathPointIdx-1], ctx->points[curPathPointIdx]), false); + if (ctx->vertCount - ctx->curVertOffset > VKVG_IBO_MAX) + return false; + curPathPointIdx = firstPathPointIdx + pathPointCount; if (ptrSegment > 0) @@ -849,7 +849,30 @@ void vkvg_stroke_preserve (VkvgContext ctx) else ptrPath++; } - //_record_draw_cmd(ctx); + + + + + return true; +} + +void vkvg_stroke_preserve (VkvgContext ctx) +{ + if (ctx->pathPtr == 0 && _current_path_is_empty(ctx))//nothing to stroke + return; + _finish_path(ctx); + + LOG(VKVG_LOG_INFO, "STROKE: ctx = %p; path ptr = %d;\n", ctx, ctx->pathPtr); + + uint32_t tmpVxCount = ctx->vertCount; + uint32_t tmpIxCount = ctx->indCount; + + if (!_process_stroke(ctx)) { + ctx->vertCount = tmpVxCount; + ctx->indCount = tmpIxCount; + _flush_undrawn_vertices(ctx);//limit draw call to addressable vx with choosen index type + _process_stroke(ctx); + } } void vkvg_paint (VkvgContext ctx){ if (ctx->pathPtr || ctx->segmentPtr){//path to fill diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index 1458e35..05fcbde 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -243,7 +243,9 @@ void _create_vertices_buff (VkvgContext ctx){ void _resize_vbo (VkvgContext ctx, uint32_t new_size) { _wait_flush_fence (ctx);//wait previous cmd if not completed ctx->sizeVBO = new_size; - ctx->sizeVBO += ctx->sizeVBO % VKVG_VBO_SIZE; + uint32_t mod = ctx->sizeVBO % VKVG_VBO_SIZE; + if (mod > 0) + ctx->sizeVBO += VKVG_VBO_SIZE - mod; LOG(VKVG_LOG_DBG_ARRAYS, "resize VBO: new size: %d\n", ctx->sizeVBO); vkvg_buffer_destroy (&ctx->vertices); vkvg_buffer_create (ctx->pSurf->dev, @@ -253,8 +255,10 @@ void _resize_vbo (VkvgContext ctx, uint32_t new_size) { } void _resize_ibo (VkvgContext ctx, size_t new_size) { _wait_flush_fence (ctx);//wait previous cmd if not completed - ctx->sizeIBO = ctx->sizeIndices; - ctx->sizeIBO += ctx->sizeIBO % VKVG_IBO_SIZE; + ctx->sizeIBO = new_size; + uint32_t mod = ctx->sizeIBO % VKVG_IBO_SIZE; + if (mod > 0) + ctx->sizeIBO += VKVG_IBO_SIZE - mod; LOG(VKVG_LOG_DBG_ARRAYS, "resize IBO: new size: %d\n", ctx->sizeIBO); vkvg_buffer_destroy (&ctx->indices); vkvg_buffer_create (ctx->pSurf->dev, @@ -418,24 +422,30 @@ void _end_render_pass (VkvgContext ctx) { #endif ctx->renderPassBeginInfo.renderPass = ctx->pSurf->dev->renderPass; } -//stroke and non-zero draw call for solid color flush -void _flush_undrawn_vertices (VkvgContext ctx){ - if (ctx->indCount == ctx->curIndStart) - return; +void _check_vao_size (VkvgContext ctx) { if (ctx->vertCount > ctx->sizeVBO || ctx->indCount > ctx->sizeIBO){ //vbo or ibo buffers too small if (ctx->cmdStarted) { //if cmd is started buffers, are already bound, so no resize is possible //instead we flush, and clear vbo and ibo caches _end_render_pass (ctx); - _flush_vertices_caches_until_vertex_base (ctx); + if (ctx->curVertOffset > 0) + _flush_vertices_caches_until_vertex_base (ctx); vkh_cmd_end (ctx->cmd); _wait_and_submit_cmd (ctx); } _resize_vbo(ctx, ctx->sizeVertices); _resize_ibo(ctx, ctx->sizeIndices); } +} + +//stroke and non-zero draw call for solid color flush +void _flush_undrawn_vertices (VkvgContext ctx){ + if (ctx->indCount == ctx->curIndStart) + return; + + _check_vao_size(ctx); _ensure_renderpass_is_started(ctx); CmdDrawIndexed(ctx->cmd, ctx->indCount - ctx->curIndStart, 1, ctx->curIndStart, (int32_t)ctx->curVertOffset, 0); @@ -453,6 +463,7 @@ void _flush_undrawn_vertices (VkvgContext ctx){ ctx->curIndStart = ctx->indCount; ctx->curVertOffset = ctx->vertCount; } + void _flush_cmd_buff (VkvgContext ctx){ _flush_undrawn_vertices (ctx); if (!ctx->cmdStarted) diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h index 6831d62..abdf933 100644 --- a/src/vkvg_context_internal.h +++ b/src/vkvg_context_internal.h @@ -34,6 +34,13 @@ #define VKVG_PATHES_SIZE 16 #define VKVG_ARRAY_THRESHOLD 8 #define VKVG_IBO_INDEX_TYPE uint16_t +#if VKVG_IBO_INDEX_TYPE == uint16_t + #define VKVG_IBO_MAX UINT16_MAX +#else + #define VKVG_IBO_MAX UINT32_MAX +#endif + + #define CreateRgba(r, g, b, a) ((a << 24) | (r << 16) | (g << 8) | b) #ifdef VKVG_PREMULT_ALPHA @@ -209,7 +216,7 @@ void _bind_draw_pipeline (VkvgContext ctx); void _create_cmd_buff (VkvgContext ctx); void _ensure_renderpass_is_started (VkvgContext ctx); void _flush_cmd_buff (VkvgContext ctx); -void _flush_undrawn_vertices (VkvgContext ctx); +void _flush_undrawn_vertices(VkvgContext ctx); void _wait_flush_fence (VkvgContext ctx); void _reset_flush_fence (VkvgContext ctx); void _wait_and_submit_cmd (VkvgContext ctx); -- 2.47.3