aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2020-04-21 18:27:11 +0300
committerAqua-sama <aqua@iserlohn-fortress.net>2020-04-21 18:27:11 +0300
commita77ef087d5d59be2d88d4921199e1e911726a517 (patch)
treed2892e2a526e461e50287e53c5a1a37d3b21076a
parentRewrite configuration tests in catch2 (diff)
downloadsmolbote-a77ef087d5d59be2d88d4921199e1e911726a517.tar.xz
Add libfuzzer test to libconfiguration
-rw-r--r--.gitignore2
-rw-r--r--lib/configuration/configuration.cpp101
-rw-r--r--lib/configuration/configuration.h3
-rw-r--r--lib/configuration/meson.build10
-rw-r--r--lib/configuration/qt_specialization.h2
-rw-r--r--lib/configuration/test/corpus/apple.txt1
-rw-r--r--lib/configuration/test/corpus/banana.txt1
-rw-r--r--lib/configuration/test/corpus/orange.txt1
8 files changed, 84 insertions, 37 deletions
diff --git a/.gitignore b/.gitignore
index f7e29ea..43ad28c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,5 @@ tools/src/crashhandler/defaults.go
.config.old
compile_commands.json
+lib/configuration/test/corpus
+
diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp
index 01a5080..75f863c 100644
--- a/lib/configuration/configuration.cpp
+++ b/lib/configuration/configuration.cpp
@@ -7,21 +7,17 @@
*/
#include "configuration.h"
-#include <QStandardPaths>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
-static std::unique_ptr<Configuration> s_conf;
-
-inline void strip(std::string &value)
-{
- value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
+#ifndef NO_QT_SPEC
+#include <QStandardPaths>
+#endif
- value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end());
-}
+static std::unique_ptr<Configuration> s_conf;
Configuration::Configuration()
: use_global(true)
@@ -32,7 +28,9 @@ Configuration::Configuration()
}
Configuration::Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> l) noexcept
+#ifndef NO_QT_SPEC
: m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString())
+#endif
{
for(const auto &i : l) {
insert_or_assign(i.first, i.second);
@@ -48,10 +46,61 @@ void Configuration::read_file(const std::string &location)
}
}
+inline auto strip(std::string &value)
+{
+ value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
+ value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end());
+ return value;
+}
+
+inline auto parse(const std::string &line, std::string &section)
+{
+ struct {
+ bool pair = false;
+ std::string key;
+ std::string value;
+ } ret;
+
+ if(line[0] == '#' || line.length() == 0) {
+ return ret;
+ }
+
+ if(line.front() == '[' && line.back() == ']') {
+ section = line.substr(1, line.length() - 2) + '/';
+ return ret;
+ }
+
+ const auto pos = line.find_first_of('=');
+ if(pos == std::string::npos) {
+ return ret;
+ }
+
+ ret.key = line.substr(0, pos);
+ strip(ret.key);
+ if(ret.key.empty()) {
+ return ret;
+ }
+ ret.key = section + ret.key;
+
+ ret.value = line.substr(pos + 1);
+ strip(ret.value);
+
+ ret.pair = true;
+ return ret;
+}
+
+#ifdef FUZZER
+extern "C" int LLVMFuzzerTestOneInput(const char *Data, long long Size)
+{
+ std::string section;
+ parse(std::string(Data, Size), section);
+ return 0;
+}
+#endif
+
void Configuration::read(std::basic_istream<char> &input)
{
- std::string line, section, key, value;
- std::istringstream is_line;
+ std::string line, section;
while(std::getline(input, line)) {
if(line.rfind("@@") == 0) {
@@ -60,39 +109,23 @@ void Configuration::read(std::basic_istream<char> &input)
}
continue;
}
- if(line[0] == '#' || line.length() == 0) {
- continue;
- }
-
- if(line.front() == '[' && line.back() == ']') {
- section = line.substr(1, line.length() - 2) + '/';
- continue;
- }
-
- is_line.clear();
- is_line.str(line);
-
- const auto pos = line.find_first_of('=');
- if(pos != std::string::npos) {
- key = section + line.substr(0, pos);
- value = line.substr(pos + 1);
- strip(key);
- strip(value);
+ const auto pair = parse(line, section);
+ if(pair.pair) {
- if(this->count(key) == 0) {
+ if(this->count(pair.key) == 0) {
// no type has been specified for this key, assuming std::string
- insert(std::make_pair(key, value));
+ insert(std::make_pair(pair.key, pair.value));
continue;
}
- auto v = at(key);
+ auto v = at(pair.key);
if(std::holds_alternative<std::string>(v)) {
- at(key) = value;
+ at(pair.key) = pair.value;
} else if(std::holds_alternative<int>(v)) {
- at(key) = std::stoi(value);
+ at(pair.key) = std::stoi(pair.value);
} else if(std::holds_alternative<bool>(v)) {
- at(key) = (value == "true");
+ at(pair.key) = (pair.value == "true");
}
}
}
diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h
index 9816ab7..09c41a0 100644
--- a/lib/configuration/configuration.h
+++ b/lib/configuration/configuration.h
@@ -9,7 +9,6 @@
#ifndef SMOLBOTE_CONFIGURATION_H
#define SMOLBOTE_CONFIGURATION_H
-#include <QAction>
#include <initializer_list>
#include <memory>
#include <optional>
@@ -136,7 +135,9 @@ private:
const bool use_global = false;
};
+#ifndef NO_QT_SPEC
#include "qt_specialization.h"
+#endif
std::ostream &operator<<(std::ostream &out, const Configuration &obj);
diff --git a/lib/configuration/meson.build b/lib/configuration/meson.build
index 104f046..59ddb7a 100644
--- a/lib/configuration/meson.build
+++ b/lib/configuration/meson.build
@@ -3,7 +3,7 @@ dep_configuration = declare_dependency(
link_with: static_library('configuration', ['configuration.cpp', 'qt_specialization.cpp'], dependencies: dep_qt5)
)
-test('configuration', executable('configuration-parser',
+test('conf parser', executable('configuration-parser',
sources: [ 'test/main.cpp' ],
dependencies: [ dep_qt5, dep_catch, dep_configuration ]
),
@@ -12,3 +12,11 @@ test('configuration', executable('configuration-parser',
workdir: meson.current_source_dir()/'test'
)
+if meson.get_compiler('cpp').has_multi_arguments('-g', '-fsanitize=fuzzer')
+test('conf fuzzer', executable('configuration-fuzzer',
+ sources: 'configuration.cpp',
+ cpp_args: [ '-g', '-fsanitize=fuzzer', '-DNO_QT_SPEC', '-DFUZZER' ],
+ link_args: [ '-fsanitize=fuzzer' ]),
+ args: [ '-seed=1', '-max_total_time=24', meson.current_source_dir()/'test/corpus' ]
+)
+endif
diff --git a/lib/configuration/qt_specialization.h b/lib/configuration/qt_specialization.h
index ea16fe0..9634261 100644
--- a/lib/configuration/qt_specialization.h
+++ b/lib/configuration/qt_specialization.h
@@ -1,5 +1,6 @@
#pragma once
+#include <QAction>
#include <QString>
#include <QStringList>
@@ -12,4 +13,3 @@ template <>
callable_when(unconsumed) QAction &Configuration::shortcut(QAction &, const char *) const;
template <>
callable_when(unconsumed) QKeySequence &Configuration::shortcut(QKeySequence &, const char *) const;
-
diff --git a/lib/configuration/test/corpus/apple.txt b/lib/configuration/test/corpus/apple.txt
new file mode 100644
index 0000000..7b89edb
--- /dev/null
+++ b/lib/configuration/test/corpus/apple.txt
@@ -0,0 +1 @@
+key=value
diff --git a/lib/configuration/test/corpus/banana.txt b/lib/configuration/test/corpus/banana.txt
new file mode 100644
index 0000000..399727c
--- /dev/null
+++ b/lib/configuration/test/corpus/banana.txt
@@ -0,0 +1 @@
+[section]
diff --git a/lib/configuration/test/corpus/orange.txt b/lib/configuration/test/corpus/orange.txt
new file mode 100644
index 0000000..308ec1d
--- /dev/null
+++ b/lib/configuration/test/corpus/orange.txt
@@ -0,0 +1 @@
+# comment