From 1690bb85bf77a77a80abf2d369b6ec17b87ab4f8 Mon Sep 17 00:00:00 2001 From: Martchus Date: Sat, 26 Jun 2021 22:24:12 +0200 Subject: [PATCH 32/32] Fix crashes in rasterization code using setjmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use C++ exceptions instead of setjmp to workaround crashes * The setjmp/longjmp code crashes when compiling for x86_64-w64-mingw32 with GCC 11 and optimizations enabled¹. It crashes when jumping back to handle the case of insufficient memory. This change uses C++ exceptions instead (turning the compile unit into a C++ unit instead of just using C) which should behave identical but don't seem to crash. * Fix rendering certain SVGs and possibly other graphics Change-Id: I01937d13569dd01ab4cb1f608020544c93bc343c --- ¹ See https://bugreports.qt.io/browse/QTBUG-94692 for details. --- src/gui/painting/painting.pri | 4 +- .../{qgrayraster.c => qgrayraster.cpp} | 41 ++++++++----------- src/gui/painting/qt_attribution.json | 2 +- 3 files changed, 21 insertions(+), 26 deletions(-) rename src/gui/painting/{qgrayraster.c => qgrayraster.cpp} (98%) diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index bb0fc0ffbae..72decdefbf2 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -1,5 +1,7 @@ # Qt gui library, paint module +CONFIG += exceptions + HEADERS += \ painting/qbackingstore.h \ painting/qbezier_p.h \ @@ -80,7 +82,7 @@ SOURCES += \ painting/qcosmeticstroker.cpp \ painting/qdrawhelper.cpp \ painting/qemulationpaintengine.cpp \ - painting/qgrayraster.c \ + painting/qgrayraster.cpp \ painting/qicc.cpp \ painting/qimagescale.cpp \ painting/qmatrix.cpp \ diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.cpp similarity index 98% rename from src/gui/painting/qgrayraster.c rename to src/gui/painting/qgrayraster.cpp index 0143e9b6027..803a676e1af 100644 --- a/src/gui/painting/qgrayraster.c +++ b/src/gui/painting/qgrayraster.cpp @@ -39,7 +39,7 @@ /***************************************************************************/ /* */ -/* qgrayraster.c, derived from ftgrays.c */ +/* qgrayraster.cpp, derived from ftgrays.c */ /* */ /* A new `perfect' anti-aliasing renderer (body). */ /* */ @@ -157,17 +157,12 @@ # include /* needed for setjmp.h */ #endif #include /* for qt_ft_memcpy() */ -#include #include #define QT_FT_UINT_MAX UINT_MAX #define qt_ft_memset memset -#define qt_ft_setjmp setjmp -#define qt_ft_longjmp longjmp -#define qt_ft_jmp_buf jmp_buf - #include typedef ptrdiff_t QT_FT_PtrDist; @@ -177,6 +172,8 @@ typedef ptrdiff_t QT_FT_PtrDist; #define ErrRaster_Memory_Overflow -4 #define ErrRaster_OutOfMemory -6 +struct RasterMemoryOverflow {}; + #define QT_FT_BEGIN_HEADER #define QT_FT_END_HEADER @@ -312,8 +309,6 @@ QT_FT_END_STMNT int band_size; int band_shoot; - qt_ft_jmp_buf jump_buffer; - void* buffer; long buffer_size; @@ -335,12 +330,14 @@ QT_FT_END_STMNT } TRaster, *PRaster; + extern "C" { int q_gray_rendered_spans(TRaster *raster) { if ( raster && raster->worker ) return raster->worker->skip_spans > 0 ? 0 : -raster->worker->skip_spans; return 0; } + } /*************************************************************************/ /* */ @@ -406,7 +403,6 @@ QT_FT_END_STMNT ras.max_ey = ( ras.max_ey + 63 ) >> 6; } - /*************************************************************************/ /* */ /* Record the current cell in the table. */ @@ -435,7 +431,7 @@ QT_FT_END_STMNT } if ( ras.num_cells >= ras.max_cells ) - qt_ft_longjmp( ras.jump_buffer, 1 ); + throw RasterMemoryOverflow(); cell = ras.cells + ras.num_cells++; cell->x = x; @@ -1507,7 +1503,7 @@ QT_FT_END_STMNT QT_FT_TRACE5(( " move to (%.2f, %.2f)\n", v_start.x / 64.0, v_start.y / 64.0 )); - error = gray_move_to( &v_start, user ); + error = gray_move_to( &v_start, static_cast(user) ); if ( error ) goto Exit; @@ -1529,7 +1525,7 @@ QT_FT_END_STMNT QT_FT_TRACE5(( " line to (%.2f, %.2f)\n", vec.x / 64.0, vec.y / 64.0 )); - gray_render_line(user, UPSCALE(vec.x), UPSCALE(vec.y)); + gray_render_line(static_cast(user), UPSCALE(vec.x), UPSCALE(vec.y)); continue; } @@ -1558,7 +1554,7 @@ QT_FT_END_STMNT " with control (%.2f, %.2f)\n", vec.x / 64.0, vec.y / 64.0, v_control.x / 64.0, v_control.y / 64.0 )); - gray_render_conic(user, &v_control, &vec); + gray_render_conic(static_cast(user), &v_control, &vec); continue; } @@ -1572,7 +1568,7 @@ QT_FT_END_STMNT " with control (%.2f, %.2f)\n", v_middle.x / 64.0, v_middle.y / 64.0, v_control.x / 64.0, v_control.y / 64.0 )); - gray_render_conic(user, &v_control, &v_middle); + gray_render_conic(static_cast(user), &v_control, &v_middle); v_control = vec; goto Do_Conic; @@ -1582,7 +1578,7 @@ QT_FT_END_STMNT " with control (%.2f, %.2f)\n", v_start.x / 64.0, v_start.y / 64.0, v_control.x / 64.0, v_control.y / 64.0 )); - gray_render_conic(user, &v_control, &v_start); + gray_render_conic(static_cast(user), &v_control, &v_start); goto Close; } @@ -1617,7 +1613,7 @@ QT_FT_END_STMNT vec.x / 64.0, vec.y / 64.0, vec1.x / 64.0, vec1.y / 64.0, vec2.x / 64.0, vec2.y / 64.0 )); - gray_render_cubic(user, &vec1, &vec2, &vec); + gray_render_cubic(static_cast(user), &vec1, &vec2, &vec); continue; } @@ -1626,7 +1622,7 @@ QT_FT_END_STMNT v_start.x / 64.0, v_start.y / 64.0, vec1.x / 64.0, vec1.y / 64.0, vec2.x / 64.0, vec2.y / 64.0 )); - gray_render_cubic(user, &vec1, &vec2, &v_start); + gray_render_cubic(static_cast(user), &vec1, &vec2, &v_start); goto Close; } } @@ -1635,7 +1631,7 @@ QT_FT_END_STMNT /* close the contour with a line segment */ QT_FT_TRACE5(( " line to (%.2f, %.2f)\n", v_start.x / 64.0, v_start.y / 64.0 )); - gray_render_line(user, UPSCALE(v_start.x), UPSCALE(v_start.y)); + gray_render_line(static_cast(user), UPSCALE(v_start.x), UPSCALE(v_start.y)); Close: first = last + 1; @@ -1663,14 +1659,11 @@ QT_FT_END_STMNT { volatile int error = 0; - if ( qt_ft_setjmp( ras.jump_buffer ) == 0 ) - { + try { error = QT_FT_Outline_Decompose( &ras.outline, &ras ); if ( !ras.invalid ) gray_record_cell( RAS_VAR ); - } - else - { + } catch (const RasterMemoryOverflow &) { error = ErrRaster_Memory_Overflow; } @@ -1932,7 +1925,7 @@ QT_FT_END_STMNT static int gray_raster_new( QT_FT_Raster* araster ) { - *araster = malloc(sizeof(TRaster)); + *araster = static_cast(malloc(sizeof(TRaster))); if (!*araster) { *araster = 0; return ErrRaster_Memory_Overflow; diff --git a/src/gui/painting/qt_attribution.json b/src/gui/painting/qt_attribution.json index 1a2b907606a..746a41efa8e 100644 --- a/src/gui/painting/qt_attribution.json +++ b/src/gui/painting/qt_attribution.json @@ -4,7 +4,7 @@ "Name": "Anti-aliasing rasterizer from FreeType 2", "QDocModule": "qtgui", "QtUsage": "Used in Qt GUI.", - "Path": "qgrayraster.c", + "Path": "qgrayraster.cpp", "Description": "FreeType is a freely available software library to render fonts.", "Homepage": "http://www.freetype.org", -- 2.44.0