aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src/vcpkg-fuzz/main.cpp
diff options
context:
space:
mode:
authornicole mazzuca <mazzucan@outlook.com>2020-04-17 18:16:20 -0700
committerGitHub <noreply@github.com>2020-04-17 18:16:20 -0700
commit09af1e9b55fdb79ef5aa04de3f1710759b2de990 (patch)
treefc151fb148667d5cf10bf3dcd8e26b5d04cc6d16 /toolsrc/src/vcpkg-fuzz/main.cpp
parent556325a1f7b6049d91565257c00db2f0bf1eadc5 (diff)
downloadvcpkg-09af1e9b55fdb79ef5aa04de3f1710759b2de990.tar.gz
vcpkg-09af1e9b55fdb79ef5aa04de3f1710759b2de990.zip
[vcpkg] Add initial JSON support (#10521)
* [vcpkg] Add initial JSON support This adds a JSON parser, as well as the amount of unicode support required for JSON parsing to work according to the specification. In the future, I hope to rewrite our existing XML files into JSON. Additionally, as a drive-by, we've added the following: * add /wd4800 to pragmas.h -- this is a "performance warning", for when you implicitly convert pointers or integers to bool, and shouldn't be an issue for us. * Switched Parse::ParserBase to read unicode (as utf-8), as opposed to ASCII * Building again under VCPKG_DEVELOPMENT_WARNINGS, yay!
Diffstat (limited to 'toolsrc/src/vcpkg-fuzz/main.cpp')
-rw-r--r--toolsrc/src/vcpkg-fuzz/main.cpp144
1 files changed, 144 insertions, 0 deletions
diff --git a/toolsrc/src/vcpkg-fuzz/main.cpp b/toolsrc/src/vcpkg-fuzz/main.cpp
new file mode 100644
index 000000000..881577654
--- /dev/null
+++ b/toolsrc/src/vcpkg-fuzz/main.cpp
@@ -0,0 +1,144 @@
+#include <vcpkg/base/checks.h>
+#include <vcpkg/base/json.h>
+#include <vcpkg/base/stringview.h>
+#include <vcpkg/base/system.print.h>
+
+#include <iostream>
+#include <sstream>
+#include <string.h>
+#include <utility>
+
+using namespace vcpkg;
+
+namespace
+{
+ enum class FuzzKind
+ {
+ None,
+ Utf8Decoder,
+ JsonParser,
+ };
+
+ struct FuzzArgs
+ {
+ FuzzArgs(int argc, char** argv)
+ {
+ if (argc <= 1)
+ {
+ print_help_and_exit();
+ }
+
+ char** it = argv + 1; // skip the name of the program
+ char** last = argv + argc;
+
+ for (; it != last; ++it)
+ {
+ auto arg = StringView(*it, strlen(*it));
+ if (arg == "/?")
+ {
+ print_help_and_exit();
+ }
+
+ auto pr = split_arg(arg);
+ auto key = pr.first;
+ auto value = pr.second;
+ if (key == "h" || key == "help")
+ {
+ print_help_and_exit();
+ }
+
+ if (key == "kind")
+ {
+ if (value == "json")
+ {
+ kind = FuzzKind::JsonParser;
+ }
+ else if (value == "utf-8")
+ {
+ kind = FuzzKind::Utf8Decoder;
+ }
+ else
+ {
+ System::print2(System::Color::error, "Invalid kind: ", value, "\n");
+ System::print2(System::Color::error, " Expected one of: utf-8, json\n\n");
+ print_help_and_exit(true);
+ }
+ }
+ else
+ {
+ System::print2("Unknown option: ", key, "\n\n");
+ print_help_and_exit(true);
+ }
+ }
+ }
+
+ // returns {arg, ""} when there isn't an `=`
+ // skips preceding `-`s
+ std::pair<StringView, StringView> split_arg(StringView arg)
+ {
+ auto first = std::find_if(arg.begin(), arg.end(), [](char c) { return c != '-'; });
+ auto division = std::find(first, arg.end(), '=');
+ if (division == arg.end()) {
+ return {StringView(first, arg.end()), StringView(arg.end(), arg.end())};
+ } else {
+ return {StringView(first, division), StringView(division + 1, arg.end())};
+ }
+ }
+
+ [[noreturn]] void print_help_and_exit(bool invalid = false)
+ {
+ constexpr auto help =
+ R"(
+Usage: vcpkg-fuzz <options>
+
+Accepts input on stdin.
+
+Options:
+ --kind=... One of {utf-8, json}
+)";
+
+ auto color = invalid ? System::Color::error : System::Color::success;
+
+ System::print2(color, help);
+ if (invalid)
+ {
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ else
+ {
+ Checks::exit_success(VCPKG_LINE_INFO);
+ }
+ }
+
+ FuzzKind kind;
+ };
+
+ std::string read_all_of_stdin()
+ {
+ std::stringstream ss;
+ ss << std::cin.rdbuf();
+ return std::move(ss).str();
+ }
+
+}
+
+int main(int argc, char** argv)
+{
+ auto args = FuzzArgs(argc, argv);
+
+ if (args.kind == FuzzKind::None)
+ {
+ args.print_help_and_exit(true);
+ }
+
+ auto text = read_all_of_stdin();
+ auto res = Json::parse(text);
+ if (!res)
+ {
+ System::print2(System::Color::error, res.error()->format());
+ }
+ else
+ {
+ System::print2(System::Color::success, "success!");
+ }
+}