fix: comprehensive boot warnings and exceptions — fixable silenced, unfixable diagnosed

Build system (5 gaps hardened):
- COOKBOOK_OFFLINE defaults to true (fork-mode)
- normalize_patch handles diff -ruN format
- New 'repo validate-patches' command (25/25 relibc patches)
- 14 patched Qt/Wayland/display recipes added to protected list
- relibc archive regenerated with current patch chain

Boot fixes (fixable):
- Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset)
- D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped)
- redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped)
- daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch)
- udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async)
- relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs
- greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait)
- greeter-ui: built and linked (header guard unification, sem_compat stubs removed)
- mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps
- greeter config: removed stale keymapd dependency from display/greeter services
- prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified

Unfixable (diagnosed, upstream):
- i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort
- kded6/greeter-ui: page fault 0x8 — Qt library null deref
- Thread panics fd != -1 — Rust std library on Redox
- DHCP timeout / eth0 MAC — QEMU user-mode networking
- hwrngd/thermald — no hardware RNG/thermal in VM
- live preload allocation — BIOS memory fragmentation, continues on demand
This commit is contained in:
2026-05-05 20:20:37 +01:00
parent a5f97b6632
commit f31522130f
81834 changed files with 11051982 additions and 108 deletions
@@ -0,0 +1,36 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_qsvggenerator Test:
#####################################################################
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qsvggenerator LANGUAGES CXX)
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
qt_internal_add_test(tst_qsvggenerator
SOURCES
tst_qsvggenerator.cpp
LIBRARIES
Qt::Gui
Qt::GuiPrivate
Qt::Svg
Qt::Xml
)
# Resources:
set(qmake_immediate_resource_files
"referenceSvgs/fileName_output.svg"
"referenceSvgs/radial_gradient.svg"
)
qt_internal_add_resource(tst_qsvggenerator "qmake_immediate"
PREFIX
"/"
FILES
${qmake_immediate_resource_files}
)
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>Qt SVG Document</title>
<desc>Generated with Qt</desc>
<defs>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >
<g fill="#ff0000" fill-opacity="1" stroke="none" transform="matrix(1,0,0,1,0,0)"
font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal"
>
<rect x="0" y="0" width="100" height="100"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 594 B

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="70.5556mm" height="35.2778mm"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>Qt SVG Document</title>
<desc>Generated with Qt</desc>
<defs>
<radialGradient gradientUnits="objectBoundingBox" cx="0.5" cy="0.5" r="0.5" fx="0.5" fy="0.5" id="gradient1">
<stop offset="0" stop-color="#ff0000" stop-opacity="1" />
<stop offset="1" stop-color="#0000ff" stop-opacity="1" />
</radialGradient>
<radialGradient gradientUnits="userSpaceOnUse" cx="150" cy="50" r="50" fx="150" fy="50" id="gradient2">
<stop offset="0" stop-color="#ff0000" stop-opacity="1" />
<stop offset="1" stop-color="#0000ff" stop-opacity="1" />
</radialGradient>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >
<g fill="url(#gradient1)" stroke="none" transform="matrix(1,0,0,1,0,0)"
font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal"
>
<rect x="0" y="0" width="100" height="100"/>
</g>
<g fill="url(#gradient2)" stroke="none" transform="matrix(1,0,0,1,0,0)"
font-family="Sans Serif" font-size="8.25" font-weight="400" font-style="normal"
>
<rect x="100" y="0" width="100" height="100"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,504 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include <qguiapplication.h>
#include <qdebug.h>
#include <qpainter.h>
#include <qsvggenerator.h>
#include <qsvgrenderer.h>
class tst_QSvgGenerator : public QObject
{
Q_OBJECT
public:
tst_QSvgGenerator();
virtual ~tst_QSvgGenerator();
private slots:
void construction();
void fileName();
void escapesTitle();
void escapesDescription();
void outputDevice();
void sizeAndViewBox();
void metric();
void radialGradient();
void fileEncoding();
void fractionalFontSize();
void titleAndDescription();
void gradientInterpolation();
void patternBrush();
};
tst_QSvgGenerator::tst_QSvgGenerator()
{
}
tst_QSvgGenerator::~tst_QSvgGenerator()
{
QFile::remove(QLatin1String("fileName_output.svg"));
QFile::remove(QLatin1String("outputDevice_output.svg"));
QFile::remove(QLatin1String("radial_gradient.svg"));
}
void tst_QSvgGenerator::construction()
{
QSvgGenerator generator;
QCOMPARE(generator.fileName(), QString());
QCOMPARE(generator.outputDevice(), (QIODevice *)0);
QCOMPARE(generator.resolution(), 72);
QCOMPARE(generator.size(), QSize());
}
static void removeAttribute(const QDomNode &node, const QString &attribute)
{
if (node.isNull())
return;
node.toElement().removeAttribute(attribute);
removeAttribute(node.firstChild(), attribute);
removeAttribute(node.nextSibling(), attribute);
}
static void compareWithoutFontInfo(const QByteArray &source, const QByteArray &reference)
{
QDomDocument sourceDoc;
sourceDoc.setContent(source);
QDomDocument referenceDoc;
referenceDoc.setContent(reference);
const QString fontAttributes[] = {
"font-family",
"font-size",
"font-weight",
"font-style",
};
for (const QString &attribute : fontAttributes) {
removeAttribute(sourceDoc, attribute);
removeAttribute(referenceDoc, attribute);
}
QCOMPARE(sourceDoc.toByteArray(), referenceDoc.toByteArray());
}
static void checkFile(const QString &fileName)
{
QVERIFY(QFile::exists(fileName));;
QFile file(fileName);
QVERIFY(file.open(QIODevice::ReadOnly));
QFile referenceFile(QFINDTESTDATA("referenceSvgs/" + fileName));
QVERIFY(referenceFile.open(QIODevice::ReadOnly));
compareWithoutFontInfo(file.readAll(), referenceFile.readAll());
}
void tst_QSvgGenerator::fileName()
{
QString fileName = "fileName_output.svg";
QFile::remove(fileName);
QSvgGenerator generator;
generator.setFileName(fileName);
QCOMPARE(generator.fileName(), fileName);
QPainter painter(&generator);
painter.fillRect(0, 0, 100, 100, Qt::red);
painter.end();
checkFile(fileName);
}
void tst_QSvgGenerator::escapesTitle()
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
const QString titleThatNeedsToBeEscaped("<malicious>\"title\" 'oh no'");
{
QSvgGenerator generator;
generator.setOutputDevice(&buffer);
generator.setTitle(titleThatNeedsToBeEscaped);
QPainter painter(&generator);
painter.end();
}
QDomDocument generated;
generated.setContent(byteArray);
const auto titleElements = generated.documentElement().elementsByTagName("title");
QCOMPARE(1, titleElements.size());
const auto theOnlyTitleElement = titleElements.at(0);
QCOMPARE(1, theOnlyTitleElement.childNodes().size());
QCOMPARE(titleThatNeedsToBeEscaped, theOnlyTitleElement.firstChild().nodeValue());
}
void tst_QSvgGenerator::escapesDescription()
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
const QString descriptionThatNeedsToBeEscaped("<evil>\"description\" 'whoopsie!'");
{
QSvgGenerator generator;
generator.setOutputDevice(&buffer);
generator.setDescription(descriptionThatNeedsToBeEscaped);
QPainter painter(&generator);
painter.end();
}
QDomDocument generated;
generated.setContent(byteArray);
const auto descriptionElements = generated.documentElement().elementsByTagName("desc");
QCOMPARE(1, descriptionElements.size());
const auto theOnlyDescriptionElement = descriptionElements.at(0);
QCOMPARE(1, theOnlyDescriptionElement.childNodes().size());
QCOMPARE(descriptionThatNeedsToBeEscaped, theOnlyDescriptionElement.firstChild().nodeValue());
}
void tst_QSvgGenerator::outputDevice()
{
QString fileName = "outputDevice_output.svg";
QFile::remove(fileName);
QFile file(fileName);
{
// Device is not open
QSvgGenerator generator;
generator.setOutputDevice(&file);
QCOMPARE(generator.outputDevice(), (QIODevice *)&file);
QPainter painter;
QVERIFY(painter.begin(&generator));
QCOMPARE(file.openMode(), QIODevice::OpenMode(QIODevice::Text | QIODevice::WriteOnly));
file.close();
}
{
// Device is not open, WriteOnly
QVERIFY(file.open(QIODevice::WriteOnly));
QSvgGenerator generator;
generator.setOutputDevice(&file);
QCOMPARE(generator.outputDevice(), (QIODevice *)&file);
QPainter painter;
QVERIFY(painter.begin(&generator));
QCOMPARE(file.openMode(), QIODevice::OpenMode(QIODevice::WriteOnly));
file.close();
}
{
// Device is not open, ReadOnly
QVERIFY(file.open(QIODevice::ReadOnly));
QSvgGenerator generator;
generator.setOutputDevice(&file);
QCOMPARE(generator.outputDevice(), (QIODevice *)&file);
QPainter painter;
QTest::ignoreMessage(QtWarningMsg, "QSvgPaintEngine::begin(), could not write to read-only output device: 'Unknown error'");
QVERIFY(!painter.begin(&generator));
QCOMPARE(file.openMode(), QIODevice::OpenMode(QIODevice::ReadOnly));
file.close();
}
}
void tst_QSvgGenerator::sizeAndViewBox()
{
{ // Setting neither properties should result in
// none of the attributes written to the SVG
QSvgGenerator generator;
QByteArray byteArray;
QBuffer buffer(&byteArray);
generator.setOutputDevice(&buffer);
QPainter painter(&generator);
painter.end();
QVERIFY(!byteArray.contains("<svg width=\""));
QVERIFY(!byteArray.contains("viewBox=\""));
}
{ // Setting size only should write size only
QSvgGenerator generator;
QByteArray byteArray;
QBuffer buffer(&byteArray);
generator.setOutputDevice(&buffer);
generator.setResolution(254);
generator.setSize(QSize(100, 100));
QPainter painter(&generator);
painter.end();
QVERIFY(byteArray.contains("<svg width=\"10mm\" height=\"10mm\""));
QVERIFY(!byteArray.contains("viewBox=\""));
}
{ // Setting viewBox only should write viewBox only
QSvgGenerator generator;
QByteArray byteArray;
QBuffer buffer(&byteArray);
generator.setOutputDevice(&buffer);
generator.setViewBox(QRectF(20, 20, 50.666, 50.666));
QPainter painter(&generator);
painter.end();
QVERIFY(!byteArray.contains("<svg width=\""));
QVERIFY(byteArray.contains("<svg viewBox=\"20 20 50.666 50.666\""));
}
{ // Setting both properties should result in
// both of the attributes written to the SVG
QSvgGenerator generator;
QByteArray byteArray;
QBuffer buffer(&byteArray);
generator.setOutputDevice(&buffer);
generator.setResolution(254);
generator.setSize(QSize(500, 500));
generator.setViewBox(QRectF(20.666, 20.666, 50, 50));
QPainter painter(&generator);
painter.end();
QVERIFY(byteArray.contains("<svg width=\"50mm\" height=\"50mm\""));
QVERIFY(byteArray.contains("viewBox=\"20.666 20.666 50 50\""));
}
}
void tst_QSvgGenerator::metric()
{
QSvgGenerator generator;
generator.setSize(QSize(100, 100));
generator.setResolution(254); // 254 dots per inch == 10 dots per mm
QCOMPARE(generator.widthMM(), 10);
QCOMPARE(generator.heightMM(), 10);
}
void tst_QSvgGenerator::radialGradient()
{
QString fileName = "radial_gradient.svg";
QFile::remove(fileName);
QSvgGenerator generator;
generator.setSize(QSize(200, 100));
generator.setFileName(fileName);
QCOMPARE(generator.fileName(), fileName);
QRadialGradient gradient(QPointF(0.5, 0.5), 0.5, QPointF(0.5, 0.5), 0);
gradient.setInterpolationMode(QGradient::ComponentInterpolation);
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::blue);
gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
QPainter painter(&generator);
painter.fillRect(0, 0, 100, 100, gradient);
gradient = QRadialGradient(QPointF(150, 50), 50, QPointF(150, 50), 0);
gradient.setInterpolationMode(QGradient::ComponentInterpolation);
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::blue);
painter.fillRect(100, 0, 100, 100, gradient);
painter.end();
checkFile(fileName);
}
void tst_QSvgGenerator::fileEncoding()
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
QSvgGenerator generator;
generator.setOutputDevice(&buffer);
static const QChar unicode[] = { 'f', 'o', 'o',
u'\u00F8', 'b', 'a', 'r'};
int size = sizeof(unicode) / sizeof(QChar);
QString unicodeString = QString::fromRawData(unicode, size);
QPainter painter(&generator);
painter.drawText(100, 100, unicodeString);
painter.end();
QVERIFY(byteArray.contains(unicodeString.toUtf8()));
}
void tst_QSvgGenerator::fractionalFontSize()
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
QSvgGenerator generator;
generator.setResolution(72);
generator.setOutputDevice(&buffer);
QPainter painter(&generator);
QFont fractionalFont = painter.font();
fractionalFont.setPointSizeF(7.5);
painter.setFont(fractionalFont);
painter.drawText(100, 100, "foo");
painter.end();
QVERIFY(byteArray.contains("7.5"));
}
void tst_QSvgGenerator::titleAndDescription()
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
QSvgGenerator generator;
generator.setTitle("foo");
QCOMPARE(generator.title(), QString("foo"));
generator.setDescription("bar");
QCOMPARE(generator.description(), QString("bar"));
generator.setOutputDevice(&buffer);
QPainter painter(&generator);
painter.end();
QVERIFY(byteArray.contains("<title>foo</title>"));
QVERIFY(byteArray.contains("<desc>bar</desc>"));
}
static void drawTestGradients(QPainter &painter)
{
int w = painter.device()->width();
int h = painter.device()->height();
if (w <= 0 || h <= 0)
h = w = 72;
QLinearGradient gradient(QPoint(0, 0), QPoint(1, 1));
gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
gradient.setColorAt(0, QColor(255, 0, 0, 0));
gradient.setColorAt(1, QColor(0, 0, 255, 255));
painter.fillRect(QRectF(0, 0, w/2, h/2), gradient);
gradient.setInterpolationMode(QGradient::ComponentInterpolation);
painter.fillRect(QRectF(0, h/2, w/2, h - h/2), gradient);
gradient.setInterpolationMode(QGradient::ColorInterpolation);
gradient.setColorAt(0, QColor(255, 0, 0, 123));
gradient.setColorAt(1, QColor(0, 0, 255, 123));
painter.fillRect(QRectF(w/2, 0, w - w/2, h/2), gradient);
gradient.setInterpolationMode(QGradient::ComponentInterpolation);
painter.fillRect(QRectF(w/2, h/2, w - w/2, h - h/2), gradient);
}
static qreal sqrImageDiff(const QImage &image1, const QImage &image2)
{
if (image1.size() != image2.size())
return 1e30;
quint64 sum = 0;
for (int y = 0; y < image1.height(); ++y) {
const quint8 *line1 = reinterpret_cast<const quint8 *>(image1.scanLine(y));
const quint8 *line2 = reinterpret_cast<const quint8 *>(image2.scanLine(y));
for (int x = 0; x < image1.width() * 4; ++x)
sum += quint64((int(line1[x]) - int(line2[x])) * (int(line1[x]) - int(line2[x])));
}
return qreal(sum) / qreal(image1.width() * image1.height());
}
void tst_QSvgGenerator::gradientInterpolation()
{
QByteArray byteArray;
QPainter painter;
QImage image(576, 576, QImage::Format_ARGB32_Premultiplied);
QImage refImage(576, 576, QImage::Format_ARGB32_Premultiplied);
image.fill(0x80208050);
refImage.fill(0x80208050);
{
QSvgGenerator generator;
QBuffer buffer(&byteArray);
generator.setOutputDevice(&buffer);
QVERIFY(painter.begin(&generator));
drawTestGradients(painter);
painter.end();
}
{
QVERIFY(painter.begin(&image));
QSvgRenderer renderer(byteArray);
renderer.render(&painter, image.rect());
painter.end();
}
{
QVERIFY(painter.begin(&refImage));
drawTestGradients(painter);
painter.end();
}
QVERIFY(sqrImageDiff(image, refImage) < 2); // pixel error < 1.41 (L2-norm)
}
void tst_QSvgGenerator::patternBrush()
{
{ // Pattern brush should create mask and pattern used as fill
QSvgGenerator generator;
QByteArray byteArray;
QBuffer buffer(&byteArray);
generator.setOutputDevice(&buffer);
QPainter painter(&generator);
painter.setBrush(Qt::CrossPattern);
painter.drawRect(0, 0, 100, 100);
painter.end();
QVERIFY(byteArray.contains("<mask id=\"patternmask"));
QVERIFY(byteArray.contains("<pattern id=\"fillpattern"));
QVERIFY(byteArray.contains("<g fill=\"url(#fillpattern"));
}
{ // Masks and patterns should be reused, not regenerated
QSvgGenerator generator;
QByteArray byteArray;
QBuffer buffer(&byteArray);
generator.setOutputDevice(&buffer);
QPainter painter(&generator);
painter.setBrush(QBrush(Qt::red, Qt::Dense3Pattern));
painter.drawRect(0, 0, 100, 100);
painter.drawEllipse(200, 50, 50, 50);
painter.setBrush(QBrush(Qt::green, Qt::Dense3Pattern));
painter.drawRoundedRect(0, 200, 100, 100, 10, 10);
painter.setBrush(QBrush(Qt::blue, Qt::Dense4Pattern));
painter.drawRect(200, 200, 100, 100);
painter.setBrush(QBrush(Qt::red, Qt::Dense3Pattern));
painter.drawRoundedRect(120, 120, 60, 60, 5, 5);
painter.end();
QCOMPARE(byteArray.count("<mask id=\"patternmask"), 2);
QCOMPARE(byteArray.count("<pattern id=\"fillpattern"), 3);
QVERIFY(byteArray.count("<g fill=\"url(#fillpattern") >= 4);
}
}
QTEST_MAIN(tst_QSvgGenerator)
#include "tst_qsvggenerator.moc"