Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commit fuzzer source code. #2

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,6 @@ tests/scripts/*.log
tests/scripts/*.trs
tests/test-suite.log
Testing/

# Vincent
build/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should be kept private. Please could you remove it from the PR?

10 changes: 8 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,14 @@ install(
# Process subdirectories
add_subdirectory(doc)
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(samples)
if (NOT (DEFINED XERCES_BUILD_FUZZERS))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these specifically excluded? It might be nicer to only use the fuzzer-specific conditions on the fuzzer code itself.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fuzzing requires some compile-time instrumentation of the xerces-library code and certain libraries that need to be linked against the instrumented code later on. Since this instrumentation is not needed for the other tests, because I thought this way it would be cleaner. Do you still want to me to change?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am afraid I misunderstand your question though: Do you want just the if condition to change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that the fuzzer keep its conditionals self-contained if possible. That is, rather than disabling other unrelated features, it should only enable or disable the fuzzing functionality. If you want to disable building of the tests and/or samples, I think they should have separate options to allow them to be enabled or disabled independently.

You could then do -Dtests=OFF -Dsamples-OFF -Dfuzzer=ON to achieve the same effect.

Also, the extra compile-time stuff using ExternalProject looks separate from building the fuzzer itself. Maybe always build the fuzzer but have that additional stuff gated on the fuzzer option. Or gate all of it. But I would put that conditional stuff inside the fuzzer CMakeLists.txt rather than having any conditionals around include statements.

add_subdirectory(tests)
add_subdirectory(samples)
endif()

if ((DEFINED XERCES_BUILD_FUZZERS) OR (DEFINED XERCES_BUILD_FOR_OSS_FUZZ))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please always include all subdirectories, and place the above conditionals around the logic inside the file. This ensures the logic is evaluated whatever the cmake options, and helps to prevent regressions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, rather than use XERCES_BUILD_FUZZERS, why not define an option fuzzers with option() defaulting to off, then you can just use -Dfuzzers=ON?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do that, thanks!

add_subdirectory(fuzzers)
endif()

# Display configuration summary
message(STATUS "")
Expand Down
8 changes: 8 additions & 0 deletions build_fuzzer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this file being used anywhere. Does it really belong in the source tree?

If it does belong, could it go into the scripts subdirectory alongside the CI scripts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily needed, but I thought it might be helpful if someone does not want to figure out the build options by themselves. Should it go into the scripts sub-directory or be completely removed?

set -e
rm -rf build
mkdir build
cd build
CC=clang CXX=clang++ CXXFLAGS="-std=c++14" cmake .. -DXERCES_BUILD_FUZZERS=1 -Wfatal-errors
CC=clang CXX=clang++ CXXFLAGS="-std=c++14" make -j8

4 changes: 2 additions & 2 deletions cmake/XercesIntTypes.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ set(HAVE_OFF_T ${SIZEOF_OFF_T})
set(HAVE_SIZE_T ${SIZEOF_SIZE_T})
set(HAVE_SSIZE_T ${SSIZEOF_SSIZE_T})
set(HAVE_WCHAR_T ${WCHAROF_WCHAR_T})
if(SIZEOF_SIZE_T)
if(HAVE_SIZEOF_SIZE_T)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure where these changes have come from. Is this a reversion of an earlier change?

If the history is messy, it might be easiest to rebase all your changes onto the current master and start a new PR.

set(XERCES_SIZE_T size_t)
set(XERCES_SIZE_MAX SIZE_MAX)
else()
set(XERCES_SIZE_T "unsigned long")
set(XERCES_SIZE_MAX ULONG_MAX)
endif()
if(SIZEOF_SSIZE_T)
if(HAVE_SIZEOF_SSIZE_T)
set(XERCES_SSIZE_T ssize_t)
set(XERCES_SSIZE_MAX SSIZE_MAX)
else()
Expand Down
6 changes: 4 additions & 2 deletions doc/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -572,14 +572,16 @@
<td>AIX PowerPC</td>
<td>IBM XL C++</td>
<td><code>./configure CXX=xlC_r CC=xlc_r</code><br/>
<code>gmake libxerces_c_la_LDFLAGS=-qmkshrobj</code></td>
<code>gmake libxerces_c_la_LDFLAGS=-qmkshrobj</code><br/>
(for xlC v11-v13, libxerces_c_la_LDFLAGS is not needed, but CXXFLAGS=-rtti is needed otherwise RTTI is disabled by default)</td>
</tr>
<tr>
<td>AIX PowerPC-64</td>
<td>IBM XL C++</td>
<td><code>export OBJECT_MODE=64</code><br/>
<code>./configure CXX=xlC_r CC=xlc_r CXXFLAGS=-q64 CFLAGS=-q64</code><br/>
<code>gmake libxerces_c_la_LDFLAGS=-qmkshrobj</code></td>
<code>gmake libxerces_c_la_LDFLAGS=-qmkshrobj</code><br/>
(for xlC v11-v13, libxerces_c_la_LDFLAGS is not needed, but CXXFLAGS="-q64 -rtti" is needed otherwise RTTI is disabled by default)</td>
</tr>
<tr>
<td>HP-UX IA-64-32</td>
Expand Down
90 changes: 90 additions & 0 deletions fuzzers/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# CMake build for xerces-c
#
# Written by Roger Leigh <[email protected]>
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Definitions required for building
add_definitions(
-DHAVE_CONFIG_H=1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is necessary, I think target_compile_definitions would be more appropriate, rather than setting it globally.

)
# Search the project binary dir for config.h
include_directories(
${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}
)

macro(add_fuzzer_executable name)
add_executable(${name} ${ARGN})
target_link_libraries(${name} xerces-c)
if (XERCES_BUILD_FUZZERS)
target_compile_options(${name} PUBLIC -fsanitize=fuzzer-no-link)
target_link_libraries(${name} -fsanitize=fuzzer)
elseif(XERCES_BUILD_FOR_OSS_FUZZ)
target_link_libraries(${name} $ENV{LIB_FUZZING_ENGINE})
endif()
set_target_properties(${name} PROPERTIES FOLDER "Fuzzers")
endmacro()

add_fuzzer_executable(fuzz_parser_target
src/xerces_fuzz_common.cpp
src/parse_target.cpp

)

include(ExternalProject)

set(EXTERNAL_INSTALL_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/external)


ExternalProject_Add(libprotobuf-mutator
GIT_SHALLOW 1
GIT_REPOSITORY https://github.com/google/libprotobuf-mutator.git
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=false -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION}
)

set(PROTOC_PATH ${CMAKE_CURRENT_BINARY_DIR}/libprotobuf-mutator-prefix/src/libprotobuf-mutator-build/external.protobuf/bin/protoc)

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/genfiles ${CMAKE_CURRENT_BINARY_DIR}/genfiles/xml.pb.cc
DEPENDS libprotobuf-mutator
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src
COMMAND mkdir ${CMAKE_CURRENT_BINARY_DIR}/genfiles && ${PROTOC_PATH} xml.proto --cpp_out=${CMAKE_CURRENT_BINARY_DIR}/genfiles
)
add_custom_target(xml_proto_files ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/genfiles)



add_fuzzer_executable(fuzz_parser_target_proto
src/xerces_fuzz_common.cpp
src/parse_target_proto.cpp
src/xmlProtoConverter.cpp
${CMAKE_CURRENT_BINARY_DIR}/genfiles/xml.pb.cc
)
add_dependencies(fuzz_parser_target_proto xml_proto_files)
add_dependencies(fuzz_parser_target_proto libprotobuf-mutator)
target_include_directories(fuzz_parser_target_proto PUBLIC ${EXTERNAL_INSTALL_LOCATION}/include
fuzz_parser_target_proto PUBLIC ${EXTERNAL_INSTALL_LOCATION}/include/libprotobuf-mutator/
${EXTERNAL_INSTALL_LOCATION}/../libprotobuf-mutator-prefix/src/libprotobuf-mutator-build/external.protobuf/include
fuzz_parser_target_proto PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/genfiles
)
target_link_libraries(fuzz_parser_target_proto
${EXTERNAL_INSTALL_LOCATION}/lib/libprotobuf-mutator-libfuzzer.a
${EXTERNAL_INSTALL_LOCATION}/lib/libprotobuf-mutator.a
${CMAKE_CURRENT_BINARY_DIR}/libprotobuf-mutator-prefix/src/libprotobuf-mutator-build/external.protobuf/src/external.protobuf-build/libprotobuf.a)

28 changes: 28 additions & 0 deletions fuzzers/src/parse_target.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
*/
#include "xerces_fuzz_common.h"

#include "xercesc/framework/MemBufInputSource.hpp"
#include "xercesc/parsers/SAXParser.hpp"
#include "xercesc/util/OutOfMemoryException.hpp"

using namespace xercesc_3_2;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
parseInMemory(Data, Size);
return 0;
}
45 changes: 45 additions & 0 deletions fuzzers/src/parse_target_proto.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
*/
#include "xerces_fuzz_common.h"
#include "xmlProtoConverter.h"

#include "xercesc/framework/MemBufInputSource.hpp"
#include "xercesc/parsers/SAXParser.hpp"
#include "xercesc/util/OutOfMemoryException.hpp"

#include "xml.pb.h"

#include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h"

#include <iostream>

namespace {
protobuf_mutator::protobuf::LogSilencer log_silincer;
void ignore(void* ctx, const char* msg, ...) {}

template <class T, class D>
std::unique_ptr<T, D> MakeUnique(T* obj, D del) {
return {obj, del};
}
}

using namespace xercesc_3_2;

DEFINE_PROTO_FUZZER(const xmlProtoFuzzer::XmlDocument& xmlDocument) {
std::string xmlData = xmlProtoFuzzer::ProtoConverter().protoToString(xmlDocument);
parseInMemory((const uint8_t *)xmlData.c_str(), xmlData.size());
}
47 changes: 47 additions & 0 deletions fuzzers/src/xerces_fuzz_common.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
*/
#include "xerces_fuzz_common.h"

using namespace xercesc_3_2;
static bool initialized = false;

void parseInMemory(const uint8_t *Data, size_t Size)
{
if (!initialized)
{
XMLPlatformUtils::Initialize();
initialized = true;
}
SAXParser::ValSchemes valScheme = SAXParser::Val_Auto;
bool doNamespaces = false;
bool doSchema = false;
bool schemaFullChecking = false;
SAXParser *parser = new SAXParser;
parser->setValidationScheme(valScheme);
parser->setDoNamespaces(doNamespaces);
parser->setDoSchema(doSchema);
parser->setHandleMultipleImports(true);
parser->setValidationSchemaFullChecking(schemaFullChecking);
static const char *gMemBufId = "prodInfo";

MemBufInputSource *memBufIS = new MemBufInputSource(
(const XMLByte *)Data, Size, gMemBufId, false);
parser->parse(*memBufIS);
delete parser;
delete memBufIS;
//XMLPlatformUtils::Terminate();
}
23 changes: 23 additions & 0 deletions fuzzers/src/xerces_fuzz_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
*/
#pragma once

#include "xercesc/parsers/SAXParser.hpp"
#include "xercesc/framework/MemBufInputSource.hpp"
#include "xercesc/util/OutOfMemoryException.hpp"

void parseInMemory(const uint8_t *Data, size_t Size);
Loading