diff options
author | Ravi Jotwani <rjotwani@google.com> | 2020-08-11 16:43:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-11 16:43:16 -0700 |
commit | 934898182204fced2cf9c7235770e9c592be7940 (patch) | |
tree | 9dfbabeca098ab07dc50cb7b40a1b2dca4c95e69 /projects/alembic | |
parent | 425b3689e248fbc0f6e40b05d67c017022d6612a (diff) | |
download | oss-fuzz-934898182204fced2cf9c7235770e9c592be7940.tar.gz |
[alembic] Initial integration (#4236)
* initial commit
* removed instances of cout in fuzzer, build failing
* Fix the Alembic build.
This commit gets Alembic building properly by linking it against
a locally compiled checkout of the most recent OpenEXR release.
* placed temp file in /tmp, modified build script
* added zlib1g-dev:i386 as a dependency in Dockerfile
* style fixes, removed msan
* combine dumpAttribute functions
* fix formatting
* update fuzzer_temp_file.h, style fixes for fuzzer
* populate target names
* disable ubsan for the time being
Co-authored-by: Michael Jezierny <mtjz@google.com>
Diffstat (limited to 'projects/alembic')
-rw-r--r-- | projects/alembic/Dockerfile | 29 | ||||
-rw-r--r-- | projects/alembic/alembic_dump_info_fuzzer.cc | 204 | ||||
-rw-r--r-- | projects/alembic/build.sh | 52 | ||||
-rw-r--r-- | projects/alembic/fuzzer_temp_file.h | 81 | ||||
-rw-r--r-- | projects/alembic/project.yaml | 6 |
5 files changed, 372 insertions, 0 deletions
diff --git a/projects/alembic/Dockerfile b/projects/alembic/Dockerfile new file mode 100644 index 000000000..baf498d34 --- /dev/null +++ b/projects/alembic/Dockerfile @@ -0,0 +1,29 @@ + +# Copyright 2020 Google Inc. +# +# 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. +# +################################################################################ + +FROM gcr.io/oss-fuzz-base/base-builder +RUN apt-get update && apt-get install -y build-essential zlib1g-dev zlib1g-dev:i386 python make automake + +RUN git clone --depth 1 https://github.com/alembic/alembic + +# Ubuntu's libilmbase-dev package doesn't include static libraries, so we have +# to build OpenEXR from source. The v2.4.2 release is the most recent as of +# 2020-07-29. +RUN git clone -b v2.4.2 --depth 1 https://github.com/AcademySoftwareFoundation/openexr + +COPY build.sh *.h *.cc $SRC/ +WORKDIR $WORK/ diff --git a/projects/alembic/alembic_dump_info_fuzzer.cc b/projects/alembic/alembic_dump_info_fuzzer.cc new file mode 100644 index 000000000..e3aa716af --- /dev/null +++ b/projects/alembic/alembic_dump_info_fuzzer.cc @@ -0,0 +1,204 @@ +// Copyright 2020 Google LLC +// +// 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 <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "alembic/lib/Alembic/AbcCoreFactory/All.h" +#include "alembic/lib/Alembic/AbcCoreOgawa/All.h" +#include "alembic/lib/Alembic/AbcGeom/All.h" +#include "alembic/lib/Alembic/AbcMaterial/All.h" + +#include "fuzzer_temp_file.h" + +using Alembic::AbcCoreAbstract::PropertyHeader; +using Alembic::AbcCoreAbstract::PropertyType; +using Alembic::AbcCoreFactory::IFactory; +using Alembic::AbcGeom::C4fArraySamplePtr; +using Alembic::AbcGeom::IArchive; +using Alembic::AbcGeom::IC4fGeomParam; +using Alembic::AbcGeom::ICompoundProperty; +using Alembic::AbcGeom::ICurves; +using Alembic::AbcGeom::ICurvesSchema; +using Alembic::AbcGeom::IFaceSet; +using Alembic::AbcGeom::IFaceSetSchema; +using Alembic::AbcGeom::IGeomBaseSchema; +using Alembic::AbcGeom::IN3fGeomParam; +using Alembic::AbcGeom::index_t; +using Alembic::AbcGeom::Int32ArraySamplePtr; +using Alembic::AbcGeom::IObject; +using Alembic::AbcGeom::IPolyMesh; +using Alembic::AbcGeom::IPolyMeshSchema; +using Alembic::AbcGeom::ISubD; +using Alembic::AbcGeom::ISubDSchema; +using Alembic::AbcGeom::IV2fGeomParam; +using Alembic::AbcGeom::IXform; +using Alembic::AbcGeom::IXformSchema; +using Alembic::AbcGeom::M44d; +using Alembic::AbcGeom::M44f; +using Alembic::AbcGeom::N3fArraySamplePtr; +using Alembic::AbcGeom::ObjectHeader; +using Alembic::AbcGeom::P3fArraySamplePtr; +using Alembic::AbcGeom::UInt32ArraySamplePtr; +using Alembic::AbcGeom::V2fArraySamplePtr; +using Alembic::AbcMaterial::IMaterial; +using Alembic::AbcMaterial::IMaterialSchema; + +template <typename T> void dumpAttributes(T const &schema) { + + const size_t meshPropertyCount = schema.getNumProperties(); + + for (size_t p = 0; p < meshPropertyCount; p++) { + const PropertyHeader &header = schema.getPropertyHeader(p); + const PropertyType pType = header.getPropertyType(); + const std::string &name = header.getName(); + + if (name == "P") { + schema.getNumSamples(); + } else if (name == "uv" || name == "st") { + schema.getUVsParam().getNumSamples(); + } else if (name == ".arbGeomParams") { + // additional geometry elements (color sets, additional texture + // coordinates) + const ICompoundProperty geoParam = schema.getArbGeomParams(); + const size_t geoPropCount = geoParam.getNumProperties(); + + for (size_t g = 0; g < geoPropCount; g++) { + const PropertyHeader &headerGeo = geoParam.getPropertyHeader(g); + const std::string &nameGeo = headerGeo.getName(); + } + } + } +} + +void dumpPolyMesh(const IObject &node) { + const ObjectHeader &header = node.getHeader(); + const IPolyMesh mesh(node.getParent(), header.getName()); + const IPolyMeshSchema &schema = mesh.getSchema(); + + // Mesh properties + dumpAttributes(schema); +} + +void dumpSubD(const IObject &node) { + const ObjectHeader &header = node.getHeader(); + const ISubD mesh(node.getParent(), header.getName()); + const ISubDSchema &schema = mesh.getSchema(); + + dumpAttributes(schema); + schema.getSubdivisionSchemeProperty(); + schema.getFaceVaryingInterpolateBoundaryProperty(); + schema.getFaceVaryingPropagateCornersProperty(); + schema.getInterpolateBoundaryProperty(); +} + +void dumpFaceSet(const IObject &node) { + const ObjectHeader &header = node.getHeader(); + const IFaceSet faceSet(node.getParent(), header.getName()); + const IFaceSetSchema &schema = faceSet.getSchema(); + schema.getNumSamples(); +} + +void dumpCurves(const IObject &node) { + const ObjectHeader &header = node.getHeader(); + const ICurves curves(node.getParent(), header.getName()); + const ICurvesSchema &schema = curves.getSchema(); + + dumpAttributes(schema); +} + +void dumpXform(const IObject &node) { + const ObjectHeader &header = node.getHeader(); + const IXform xform(node.getParent(), header.getName()); + const IXformSchema &schema = xform.getSchema(); + + schema.getNumSamples(); + schema.getNumOps(); +} + +void dumpMaterial(const IObject &node) { + const ObjectHeader &header = node.getHeader(); + IMaterial material(node.getParent(), header.getName()); + IMaterialSchema &schema = material.getSchema(); + + std::vector<std::string> targetNames; + schema.getTargetNames(targetNames); + + for (const std::string &target : targetNames) { + std::vector<std::string> shaderTypes; + schema.getShaderTypesForTarget(target, shaderTypes); + const size_t shaderTypeCount = shaderTypes.size(); + for (size_t s = 0; s < shaderTypeCount; s++) { + + ICompoundProperty parameters = + schema.getShaderParameters(target, shaderTypes[s]); + const size_t parameterCount = parameters.getNumProperties(); + } + } +} + +void dumpNodes(const IObject &node) { + const ObjectHeader &header = node.getHeader(); + // Dump the general node information. + header.getName(); + header.getFullName(); + header.getMetaData().serialize(); + + // Dump the type specific information. + if (Alembic::AbcGeom::IPolyMesh::matches(header)) { + dumpPolyMesh(node); + } else if (Alembic::AbcGeom::ISubD::matches(header)) { + dumpSubD(node); + } else if (Alembic::AbcGeom::IFaceSet::matches(header)) { + dumpFaceSet(node); + } else if (Alembic::AbcGeom::ICurves::matches(header)) { + dumpCurves(node); + } else if (Alembic::AbcGeom::IXform::matches(header)) { + dumpXform(node); + } else if (Alembic::AbcMaterial::IMaterial::matches(header)) { + dumpMaterial(node); + } else { // Miscellaneous nodes such as the root. + ; + } + + // Dump the child headers. + const size_t childCount = node.getNumChildren(); + for (size_t i = 0; i < childCount; i++) { + dumpNodes(node.getChild(i)); + } +} + +void dumpInfo(const char *file) { + // Load the Alembic archive and verify that it is valid. + IFactory factory; + IArchive archive = factory.getArchive(file); + + if (archive.valid()) { + archive.getName(); + dumpNodes(archive.getTop()); + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzerTemporaryFile tempFile(data, size); + dumpInfo(tempFile.filename()); + + return 0; +} diff --git a/projects/alembic/build.sh b/projects/alembic/build.sh new file mode 100644 index 000000000..28ada7ec9 --- /dev/null +++ b/projects/alembic/build.sh @@ -0,0 +1,52 @@ +#!/bin/bash -eu +# Copyright 2020 Google Inc. +# +# 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. +# +################################################################################ + +mkdir -p $WORK/build_openexr +mkdir -p $WORK/build_alembic + +# build openexr for alembic +cd $WORK/build_openexr +OPENEXR_CMAKE_SETTINGS=( + "-D BUILD_SHARED_LIBS=OFF" # Build static libraries only + "-D PYILMBASE_ENABLE=OFF" # Don't build Python support + "-D BUILD_TESTING=OFF" # Or tests + "-D INSTALL_OPENEXR_EXAMPLES=OFF" # Or examples + "-D OPENEXR_LIB_SUFFIX=" # Don't append the version number to library files + "-D ILMBASE_LIB_SUFFIX=" +) +cmake $SRC/openexr ${OPENEXR_CMAKE_SETTINGS[@]} +make -j$(nproc) && make install + +# build alembic +cd $WORK/build_alembic +cmake $SRC/alembic -DALEMBIC_SHARED_LIBS=OFF +make -j$(nproc) + +INCLUDES=( + "-I $SRC" + "-I ${SRC}/alembic/lib" + "-I ${WORK}/build_alembic/lib" + "-I /usr/local/include/OpenEXR" +) +LIBS=("-lImath" "-lIex" "-lHalf") + +for fuzzer in $(find $SRC -name '*_fuzzer.cc'); do + fuzzer_basename=$(basename -s .cc $fuzzer) + $CXX $CXXFLAGS -std=c++11 ${INCLUDES[@]} \ + $fuzzer $WORK/build_alembic/lib/Alembic/libAlembic.a $LIB_FUZZING_ENGINE \ + -o $OUT/$fuzzer_basename ${LIBS[@]} +done diff --git a/projects/alembic/fuzzer_temp_file.h b/projects/alembic/fuzzer_temp_file.h new file mode 100644 index 000000000..b5442f164 --- /dev/null +++ b/projects/alembic/fuzzer_temp_file.h @@ -0,0 +1,81 @@ +// Copyright 2020 Google Inc. +// +// 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. + +// Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that +// require a file instead of an input buffer. + +#ifndef FUZZER_TEMP_FILE_H_ +#define FUZZER_TEMP_FILE_H_ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +// Pure-C interface for creating and cleaning up temporary files. + +static char *fuzzer_get_tmpfile(const uint8_t *data, size_t size) { + char *filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX"); + if (!filename_buffer) { + perror("Failed to allocate file name buffer."); + abort(); + } + const int file_descriptor = mkstemp(filename_buffer); + if (file_descriptor < 0) { + perror("Failed to make temporary file."); + abort(); + } + FILE *file = fdopen(file_descriptor, "wb"); + if (!file) { + perror("Failed to open file descriptor."); + close(file_descriptor); + abort(); + } + const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file); + if (bytes_written != size) { + fclose(file); + fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", + bytes_written, size); + abort(); + } + fclose(file); + return filename_buffer; +} + +static void fuzzer_release_tmpfile(char *filename) { + if (unlink(filename) != 0) { + perror("WARNING: Failed to delete temporary file."); + } + free(filename); +} + +// C++ RAII object for creating temporary files. + +#ifdef __cplusplus +class FuzzerTemporaryFile { +public: + FuzzerTemporaryFile(const uint8_t *data, size_t size) + : filename_(fuzzer_get_tmpfile(data, size)) {} + + ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); } + + const char *filename() const { return filename_; } + +private: + char *filename_; +}; +#endif + +#endif // FUZZER_TEMP_FILE_H_ diff --git a/projects/alembic/project.yaml b/projects/alembic/project.yaml new file mode 100644 index 000000000..323b0f982 --- /dev/null +++ b/projects/alembic/project.yaml @@ -0,0 +1,6 @@ +homepage: "https://github.com/alembic/alembic" +language: c++ +primary_contact: "miller.lucas@gmail.com" +sanitizers: + - address + |