mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 16:12:01 +00:00
Merge pull request #24480 from BoloniniD/yaml-fuzz
Add fuzzing tests for YAMLParser
This commit is contained in:
commit
d715395751
@ -57,7 +57,7 @@ void processNode(const YAML::Node & node, Poco::XML::Element & parent_xml_elemen
|
|||||||
{
|
{
|
||||||
case YAML::NodeType::Scalar:
|
case YAML::NodeType::Scalar:
|
||||||
{
|
{
|
||||||
auto value = node.as<std::string>();
|
std::string value = node.as<std::string>();
|
||||||
Poco::AutoPtr<Poco::XML::Text> xml_value = xml_document->createTextNode(value);
|
Poco::AutoPtr<Poco::XML::Text> xml_value = xml_document->createTextNode(value);
|
||||||
parent_xml_element.appendChild(xml_value);
|
parent_xml_element.appendChild(xml_value);
|
||||||
break;
|
break;
|
||||||
@ -110,13 +110,13 @@ void processNode(const YAML::Node & node, Poco::XML::Element & parent_xml_elemen
|
|||||||
{
|
{
|
||||||
const auto & key_node = key_value_pair.first;
|
const auto & key_node = key_value_pair.first;
|
||||||
const auto & value_node = key_value_pair.second;
|
const auto & value_node = key_value_pair.second;
|
||||||
auto key = key_node.as<std::string>();
|
std::string key = key_node.as<std::string>();
|
||||||
bool is_attribute = (key.starts_with(YAML_ATTRIBUTE_PREFIX) && value_node.IsScalar());
|
bool is_attribute = (key.starts_with(YAML_ATTRIBUTE_PREFIX) && value_node.IsScalar());
|
||||||
if (is_attribute)
|
if (is_attribute)
|
||||||
{
|
{
|
||||||
/// we use substr(1) here to remove YAML_ATTRIBUTE_PREFIX from key
|
/// we use substr(1) here to remove YAML_ATTRIBUTE_PREFIX from key
|
||||||
auto attribute_name = key.substr(1);
|
auto attribute_name = key.substr(1);
|
||||||
auto value = value_node.as<std::string>();
|
std::string value = value_node.as<std::string>();
|
||||||
parent_xml_element.setAttribute(attribute_name, value);
|
parent_xml_element.setAttribute(attribute_name, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -148,7 +148,7 @@ Poco::AutoPtr<Poco::XML::Document> YAMLParser::parse(const String& path)
|
|||||||
catch (const YAML::ParserException& e)
|
catch (const YAML::ParserException& e)
|
||||||
{
|
{
|
||||||
/// yaml-cpp cannot parse the file because its contents are incorrect
|
/// yaml-cpp cannot parse the file because its contents are incorrect
|
||||||
throw Exception(ErrorCodes::CANNOT_PARSE_YAML, "Unable to parse YAML configuration file {}", path, e.what());
|
throw Exception(ErrorCodes::CANNOT_PARSE_YAML, "Unable to parse YAML configuration file {}, {}", path, e.what());
|
||||||
}
|
}
|
||||||
catch (const YAML::BadFile&)
|
catch (const YAML::BadFile&)
|
||||||
{
|
{
|
||||||
@ -158,7 +158,14 @@ Poco::AutoPtr<Poco::XML::Document> YAMLParser::parse(const String& path)
|
|||||||
Poco::AutoPtr<Poco::XML::Document> xml = new Document;
|
Poco::AutoPtr<Poco::XML::Document> xml = new Document;
|
||||||
Poco::AutoPtr<Poco::XML::Element> root_node = xml->createElement("yandex");
|
Poco::AutoPtr<Poco::XML::Element> root_node = xml->createElement("yandex");
|
||||||
xml->appendChild(root_node);
|
xml->appendChild(root_node);
|
||||||
processNode(node_yml, *root_node);
|
try
|
||||||
|
{
|
||||||
|
processNode(node_yml, *root_node);
|
||||||
|
}
|
||||||
|
catch (const YAML::TypedBadConversion<std::string>&)
|
||||||
|
{
|
||||||
|
throw Exception(ErrorCodes::CANNOT_PARSE_YAML, "YAMLParser has encountered node with key or value which cannot be represented as string and cannot continue parsing of the file");
|
||||||
|
}
|
||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,3 +80,8 @@ target_link_libraries (average PRIVATE clickhouse_common_io)
|
|||||||
|
|
||||||
add_executable (shell_command_inout shell_command_inout.cpp)
|
add_executable (shell_command_inout shell_command_inout.cpp)
|
||||||
target_link_libraries (shell_command_inout PRIVATE clickhouse_common_io)
|
target_link_libraries (shell_command_inout PRIVATE clickhouse_common_io)
|
||||||
|
|
||||||
|
if (ENABLE_FUZZING)
|
||||||
|
add_executable(YAML_fuzzer YAML_fuzzer.cpp ${SRCS})
|
||||||
|
target_link_libraries(YAML_fuzzer PRIVATE clickhouse_parsers ${LIB_FUZZING_ENGINE})
|
||||||
|
endif ()
|
||||||
|
39
src/Common/examples/YAML_fuzzer.cpp
Normal file
39
src/Common/examples/YAML_fuzzer.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <time.h>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
/// How to test:
|
||||||
|
/// build ClickHouse with YAML_fuzzer.cpp
|
||||||
|
/// ./YAML_fuzzer YAML_CORPUS
|
||||||
|
/// where YAML_CORPUS is a directory with different YAML configs for libfuzzer
|
||||||
|
char file_name[L_tmpnam];
|
||||||
|
if (!std::tmpnam(file_name))
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot create temp file!\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::string input = std::string(reinterpret_cast<const char*>(data), size);
|
||||||
|
DB::YAMLParser parser;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ofstream temp_file(file_name);
|
||||||
|
temp_file << input;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DB::YAMLParser::parse(std::string(file_name));
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << "YAML_fuzzer failed: " << getCurrentExceptionMessage() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user