aboutsummaryrefslogtreecommitdiff
path: root/projects/alembic
diff options
context:
space:
mode:
authorRavi Jotwani <rjotwani@google.com>2020-08-11 16:43:16 -0700
committerGitHub <noreply@github.com>2020-08-11 16:43:16 -0700
commit934898182204fced2cf9c7235770e9c592be7940 (patch)
tree9dfbabeca098ab07dc50cb7b40a1b2dca4c95e69 /projects/alembic
parent425b3689e248fbc0f6e40b05d67c017022d6612a (diff)
downloadoss-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/Dockerfile29
-rw-r--r--projects/alembic/alembic_dump_info_fuzzer.cc204
-rw-r--r--projects/alembic/build.sh52
-rw-r--r--projects/alembic/fuzzer_temp_file.h81
-rw-r--r--projects/alembic/project.yaml6
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
+