qdrawhelper: (attempt to) fix Coverity warning about op being uninit'ed

Unlike in other cases of structs, Coverity doesn't say which field,
exactly, it considers uninitialized in `op` upon return from
getOperator(). Manual checking confirms that all fields are written in
all branches (and all configs, btw), with the following exceptions:

- src* fields are not written in QSpanData::None mode, but this branch
  is marked as Q_UNREACHABLE()

- `linear`/`radial` are only written in QSpanData::Linear- or
  RadialGradient mode, which means that their (unnamed) union is not
  written in Solid/ConicalGradient/Texture modes

Assuming it's the latter branch that trips Coverity, introduce a
std::monostate member, noGradient, to said union, and initialize it
Solid/ConicalGradient/Texture modes. This makes the union a kind of
optional, but without the churn of actually introducing a
std::optional<Union>.

The effect is that in those modes the active union member is now the
empty monostate, so static analyzers will not complain about `linear`
or `radial` being uninitialized (because they're not active members).

'noGradient' being the active union member should also help statically
and dynamically (ubsan, one day?) detect accesses to `linear` or
`radial` when they're not active. Before, I believe the first declared
of the two was implicitly active.

Amends the start of the public history.

Pick-to: 6.9 6.8 6.5
Coverity-Id: 11400
Change-Id: I743363cc06af3778f85c205bfb6880c696229f92
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
Marc Mutz 2025-03-04 10:41:34 +01:00
parent 275396b013
commit 8492ba01ba
2 changed files with 5 additions and 0 deletions

View File

@ -3793,6 +3793,7 @@ static inline Operator getOperator(const QSpanData *data, const QT_FT_Span *span
switch(data->type) {
case QSpanData::Solid:
solidSource = data->solidColor.alphaF() >= 1.0f;
op.noGradient = {};
op.srcFetch = nullptr;
op.srcFetch64 = nullptr;
op.srcFetchFP = nullptr;
@ -3821,6 +3822,7 @@ static inline Operator getOperator(const QSpanData *data, const QT_FT_Span *span
break;
case QSpanData::ConicalGradient:
solidSource = !data->gradient.alphaColor;
op.noGradient = {}; // sic!
op.srcFetch = qt_fetch_conical_gradient;
#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_conical_gradient_rgb64;
@ -3831,6 +3833,7 @@ static inline Operator getOperator(const QSpanData *data, const QT_FT_Span *span
break;
case QSpanData::Texture:
solidSource = !data->texture.hasAlpha;
op.noGradient = {};
op.srcFetch = getSourceFetch(getBlendType(data), data->texture.format);
#if QT_CONFIG(raster_64bit)
op.srcFetch64 = getSourceFetch64(getBlendType(data), data->texture.format);

View File

@ -30,6 +30,7 @@
#include <private/qsimd_p.h>
#include <memory>
#include <variant> // std::monostate
QT_BEGIN_NAMESPACE
@ -210,6 +211,7 @@ struct Operator
CompositionFunctionFP funcFP;
union {
std::monostate noGradient;
LinearGradientValues linear;
RadialGradientValues radial;
};