Skip to content

Commit

Permalink
test: Add the kimageformats fuzz test to third_party.
Browse files Browse the repository at this point in the history
Moving it out of qtox, because it's independent of that code.
  • Loading branch information
iphydf committed Jan 8, 2025
1 parent c4c949d commit 31385ff
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 9 deletions.
82 changes: 82 additions & 0 deletions third_party/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
# Language
Standard: Cpp11

# Indentation
IndentWidth: 4
ContinuationIndentWidth: 4
AccessModifierOffset: -4
IndentCaseLabels: false
NamespaceIndentation: None

# Spacing
UseTab: Never
SpaceBeforeParens: ControlStatements
SpacesBeforeTrailingComments: 1
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesInCStyleCastParentheses: false
SpaceBeforeAssignmentOperators: true
MaxEmptyLinesToKeep: 2

# Alignment
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true

# Argument Packing
BinPackArguments: true
BinPackParameters: true

# Break handling
ColumnLimit: 100
BreakBeforeBraces: Mozilla
BreakBeforeBinaryOperators: NonAssignment
BreakConstructorInitializersBeforeComma: true
AlwaysBreakTemplateDeclarations: true
ConstructorInitializerAllOnOneLineOrOnePerLine: false
Cpp11BracedListStyle: true

# Break penalities
PenaltyBreakBeforeFirstCallParameter: 200
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 5
PenaltyReturnTypeOnItsOwnLine: 60

# Includes
SortIncludes: true
IncludeCategories:
# Match local headers
- Regex: '^"[[:alnum:]_]+\.h"$'
Priority: 1
# Match project headers
- Regex: '^"[[:alnum:]_]+/.+\.h"$'
Priority: 2
# Match Qt headers
- Regex: '^<Q[[:alnum:]_/]+>$'
Priority: 3
# Match other headers
- Regex: '.*'
Priority: 4

# Short blocks
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty

# Set pointer format
DerivePointerAlignment: false
PointerAlignment: Left

# "const X" instead of "X const"
QualifierAlignment: Left
...
12 changes: 7 additions & 5 deletions third_party/kimageformats.BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ load("@toktok//third_party/qt:build_defs.bzl", "qt_moc")

qt_moc(
name = "kimageformats_moc",
srcs = glob(
[
"src/imageformats/*.cpp",
"src/imageformats/*_p.h",
],
srcs = ["src/imageformats/xcf.cpp"] + glob(
["src/imageformats/*_p.h"],
exclude = [
"src/imageformats/avif_p.h",
"src/imageformats/exr_p.h",
"src/imageformats/fastmath_p.h",
"src/imageformats/gimp_p.h",
"src/imageformats/jxl_p.h",
"src/imageformats/ora_p.h",
"src/imageformats/rle_p.h",
"src/imageformats/scanlineconverter_p.h",
"src/imageformats/util_p.h",
],
),
hdrs = glob(["src/imageformats/*.json"]),
Expand Down
27 changes: 27 additions & 0 deletions third_party/kimageformats/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
load("//third_party/qt:build_defs.bzl", "qt_test")

cc_fuzz_test(
name = "qimage_fuzz_test",
size = "small",
testonly = True,
srcs = ["test/qimage_fuzz_test.cpp"],
tags = ["qt"],
deps = [
"@kimageformats",
"@qt//:qt_core",
"@qt//:qt_gui",
],
)

qt_test(
name = "qimage_test",
size = "small",
src = "test/qimage_test.cpp",
tags = ["manual"],
deps = [
"@kimageformats",
"@qt//:qt_core",
"@qt//:qt_gui",
],
)
63 changes: 63 additions & 0 deletions third_party/kimageformats/test/qimage_fuzz_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <QBuffer>
#include <QByteArray>
#include <QIODevice>
#include <QImage>
#include <QImageIOPlugin>
#include <QPluginLoader>

#include <cstddef>
#include <cstdint>

namespace {
void test_fromData(const uint8_t* data, size_t size)
{
if (size == 0) {
return;
}

const auto& plugins = QPluginLoader::staticInstances();
assert(plugins.size() < 256);
if (data[0] >= plugins.size()) {
return;
}

if (auto* imagePlugin = qobject_cast<QImageIOPlugin*>(plugins[data[0]])) {
qInstallMessageHandler([](QtMsgType, const QMessageLogContext&, const QString&) {
// Ignore messages
});

QByteArray ba(reinterpret_cast<const char*>(data + 1), size - 1);
QBuffer device(&ba);
device.open(QIODevice::ReadOnly);

QImage image;

auto* handler = imagePlugin->create(&device);
if (handler && handler->canRead()) {
handler->read(&image);
}
delete handler;
}
}
} // namespace

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
test_fromData(data, size);
return 0;
}

Q_IMPORT_PLUGIN(ANIPlugin)
Q_IMPORT_PLUGIN(EPSPlugin)
Q_IMPORT_PLUGIN(HDRPlugin)
Q_IMPORT_PLUGIN(PCXPlugin)
Q_IMPORT_PLUGIN(PFMPlugin)
Q_IMPORT_PLUGIN(PSDPlugin)
Q_IMPORT_PLUGIN(PXRPlugin)
Q_IMPORT_PLUGIN(QOIPlugin)
Q_IMPORT_PLUGIN(RASPlugin)
Q_IMPORT_PLUGIN(RGBPlugin)
Q_IMPORT_PLUGIN(TGAPlugin)
Q_IMPORT_PLUGIN(XCFPlugin)
Q_IMPORT_PLUGIN(SoftimagePICPlugin)
105 changes: 105 additions & 0 deletions third_party/kimageformats/test/qimage_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2025 The TokTok team.
*/

#include <QBuffer>
#include <QByteArray>
#include <QImage>
#include <QImageIOPlugin>
#include <QPluginLoader>
#include <QTest>

#include <cassert>
#include <cstddef>
#include <dlfcn.h>

// Check if allocation size isn't too big, then call glibc's malloc.
static void* (*libc_malloc)(size_t);
static bool malloc_failed = false;

void* malloc(size_t size)
{
if (!malloc_failed && size < 100 * 1024 * 1024) {
malloc_failed = true;
}
if (!libc_malloc) {
libc_malloc = reinterpret_cast<void* (*)(size_t)>(dlsym(RTLD_NEXT, "malloc"));
}
return libc_malloc(size);
}

class TestQImage : public QObject
{
Q_OBJECT

private slots:
void testANI();
void testXCF();
void testXCFSlow();
};

// https://bugs.kde.org/show_bug.cgi?id=498368
#define BUG_498368_FIXED 1
void TestQImage::testANI()
{
#if BUG_498368_FIXED
malloc_failed = false;

const QByteArray data = QByteArray::fromBase64( //
"AFJJRkYOAACAQUNPTgB+YAAAAAAAUklGRg4AAIBBQ09OAH5gAAAAAABzZXEgANra2tra2tra2tra2t"
"ra2tra2tra2tra2tra2tra2tra2traAAAAAAAAAAAAAAAAAF0=");

QImage::fromData(data.mid(1), "ANI");
QVERIFY(!malloc_failed);
#endif
}

// https://bugs.kde.org/show_bug.cgi?id=498380
#define BUG_498380_FIXED 1
void TestQImage::testXCF()
{
#if BUG_498380_FIXED
const QByteArray data = QByteArray::fromBase64(
"AWdpbXAgeGNmAAAwAAoAAABbAAAAAzMAAAAAAAAAAAAAAAAAAAAgCHAAAC0AAAAAAAgAAAAAAAAg"
"8AAAAAAAAAAACAAAAAAgAPAAAAAACgCAAAAAAAAAAAAJ2/AAAAAAAAAAACMAAAAACHAAAAAAAAAA"
"AAgAAAAAAAAg8AAAAAAAAAAACAAAAAAgXPAAAAAACgCAAAAAAAAAAAAJ2/AAAAAAAAAAACIAAAAI"
"cAAALQAAAAAACAAAAAAAIAhwAAAtAAAAAAAIAAAAAAAAIPAAAAAAAAAAAAgAAAAAIADwAAAAAAoA"
"gAAAAAAAAAAACdvwAAAAAAAAAAAjAAAKAIAAAAAAAAAAAAnb8AAAAAAAAAAAIgAAAAhwAAAtAAAA"
"AAAIAAAAAAAgCHAAAAAAAAAg8AAAAAAAAAAACAAAAAAgAPAAPwAACgCAAAAAAAAAAAAJ2/AAAAAA"
"AAAAAPAAIABQSApg");

QImage::fromData(data.mid(1), "XCF");
#endif
}

// https://bugs.kde.org/show_bug.cgi?id=498381
#define BUG_498381_FIXED 1
void TestQImage::testXCFSlow()
{
#if BUG_498381_FIXED
const QByteArray data = QByteArray::fromBase64(
"AWdpbXAgeGNmAAAwAAoAAABbAAAAAzMAAAAAAAAAAAAAAAYAcAEAAAAAAwAAAAAAAf//////bW1t"
"bW1tbW1tbW1tbW1tbW3/////////////bW1tnZ2dnZ2dnZ2dJSFQUy1BZG9iZZ2dnZ2dnZ2dnZ2d"
"nZ2dnZ2dnZ2dnXJycnJycnJycnJycnJycnJycnJycnJycnJtfm1tbW1tbW1tAAAAAAAAAAABMQAA"
"7wYAAAAAAAAAAQAAAAAAAAAAAAAAAAkAAAAJ22M/");

QImage::fromData(data.mid(1), "XCF");
#endif
}

QTEST_GUILESS_MAIN(TestQImage)
#include "qimage_test.moc"

Q_IMPORT_PLUGIN(ANIPlugin)
// Q_IMPORT_PLUGIN(EPSPlugin)
// Q_IMPORT_PLUGIN(HDRPlugin)
// Q_IMPORT_PLUGIN(PCXPlugin)
// Q_IMPORT_PLUGIN(PFMPlugin)
// Q_IMPORT_PLUGIN(PSDPlugin)
// Q_IMPORT_PLUGIN(PXRPlugin)
// Q_IMPORT_PLUGIN(QOIPlugin)
// Q_IMPORT_PLUGIN(RASPlugin)
// Q_IMPORT_PLUGIN(RGBPlugin)
// Q_IMPORT_PLUGIN(TGAPlugin)
Q_IMPORT_PLUGIN(XCFPlugin)
// Q_IMPORT_PLUGIN(SoftimagePICPlugin)
8 changes: 4 additions & 4 deletions third_party/qt/build_defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -293,20 +293,20 @@ def qt_binary(name, tags=[], **kwargs):
# Qt test with MOC for the test .cpp file.
# =========================================================

def qt_test(name, src, deps, copts = [], mocopts = [], size = None, **kwargs):
def qt_test(name, src, deps, copts = [], mocopts = [], size = None, tags = [], **kwargs):
qt_moc(
name = "%s_moc_src" % name,
testonly = True,
srcs = [src],
mocopts = mocopts,
tags = ["qt"],
tags = ["qt"] + tags,
deps = deps,
)
cc_library(
name = "%s_moc" % name,
testonly = True,
hdrs = [":%s_moc_src" % name],
tags = ["qt"],
tags = ["qt"] + tags,
**kwargs
)
cc_test(
Expand All @@ -333,7 +333,7 @@ def qt_test(name, src, deps, copts = [], mocopts = [], size = None, **kwargs):
":%s_moc" % name,
"@qt//:qt_test",
],
tags = ["qt"],
tags = ["qt"] + tags,
**kwargs
)

Expand Down

0 comments on commit 31385ff

Please sign in to comment.