may crash before splash screen on 2.1, 2.2, or master with Qt 5.10 due to diverged copy-and-pasted QPaintEnginePrivate header file

• Feb 26, 2018 - 20:31
Reported version
2.1
Type
Functional
Severity
S3 - Major
Status
closed
Project

Was experiencing a strange segfault when use Qt 5.10. I don't know if it specifically affects armv7 but that is the only machine I am on now...the problem started I believe when arch linux moved to Qt 5.10, but it affects both the arch linux official 2.1 build, as well as when I self build 2.1 or 2.2 or master. No problem when I use an older Qt. After a long investigation (https://musescore.org/en/node/268374) I finally discovered that the problem resulted from that the fact that mscore/svngenerator.cpp's SvgPaintEnginePrivate class has been extending QPaintEnginePrivate, but the file qpaintengine_p.h was copy-and-pasted from over 6 years ago. In that file you will notice a warning from Qt:

//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

So they did mean it, and turns out after much investigation (building Qt 5.10 debug version from source and stepping through the constructor and deconstructor) I noticed some very odd things happening around this QPaintEnginePrivate class...basically it's binary memory contents were not adhering to what the C++ code says should be happening to it. I then noticed that this private Qt header qpaintengine_p.h has indeeded diverged from it's original state 6+ years ago.


Comments

Title crash before splash screen when run 2.1, 2.2, or master with Qt 5.10 (on arch linux armv7 machine) due to diverged copy-and-pasted QPaintEnginePrivate header file may crash before splash screen on 2.1, 2.2, or master with Qt 5.10 due to diverged copy-and-pasted QPaintEnginePrivate header file
Status

I'm removing "(on arch linux armv7 machine)" and instead inserted "may" at the beginning, because there doesn't seem any particular reason why this bug should only affect armv7...in fact any instruction set could potentially be affected, since the problem conflicting class definitions. It might not happen on x86-64 out of sheer luck of how the compiler happens to lays out and access the class in memory.

Status (old) patch (code needs review) fixed
Status fixed

Fixed in branch 2.2, commit 2b8c11dd47

fix #269845 Svg don't inheirt QPaintEnginePrivate

SvgPaintEnginePrivate class has always extended QPaintEnginePrivate. But QPaintEnginePrivate was defined in a header file which was copy-and-pasted from Qt over 6 years ago in the initial git commit. But with 5.10, Qt added another QRegion member to their definition of QPaintEnginePrivate to fix a bug, so the old copy-and-pasted header no longer correctly represents QPaintEnginePrivate. This conflicting definition results in a segfault whenever I tried to run mscore 2.1, 2.2, or master at least on my armv7 arch linux machine when using Qt 5.10 (although worked with Qt 5.9).

Lasconic suggested maybe try removing the inheiritance all together. Turns out SvgPaintEnginePrivate doesn't actually need to inheirit QPaintEnginePrivate. So the fix here is to remove that inheiritance and complety remove the old copy-and-pasted private header file.

Fixed in branch master, commit 5507d256b3

fix #269845 Svg don't inheirt QPaintEnginePrivate

SvgPaintEnginePrivate class has always extended QPaintEnginePrivate. But QPaintEnginePrivate was defined in a header file which was copy-and-pasted from Qt over 6 years ago in the initial git commit. But with 5.10, Qt added another QRegion member to their definition of QPaintEnginePrivate to fix a bug, so the old copy-and-pasted header no longer correctly represents QPaintEnginePrivate. This conflicting definition results in a segfault whenever I tried to run mscore 2.1, 2.2, or master at least on my armv7 arch linux machine when using Qt 5.10 (although worked with Qt 5.9).

Lasconic suggested maybe try removing the inheiritance all together. Turns out SvgPaintEnginePrivate doesn't actually need to inheirit QPaintEnginePrivate. So the fix here is to remove that inheiritance and complety remove the old copy-and-pasted private header file.