1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <err.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stddef.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23
24 #include "alembic/lib/Alembic/AbcCoreFactory/All.h"
25 #include "alembic/lib/Alembic/AbcCoreOgawa/All.h"
26 #include "alembic/lib/Alembic/AbcGeom/All.h"
27 #include "alembic/lib/Alembic/AbcMaterial/All.h"
28
29 #include "fuzzer_temp_file.h"
30
31 using Alembic::AbcCoreAbstract::PropertyHeader;
32 using Alembic::AbcCoreAbstract::PropertyType;
33 using Alembic::AbcCoreFactory::IFactory;
34 using Alembic::AbcGeom::C4fArraySamplePtr;
35 using Alembic::AbcGeom::IArchive;
36 using Alembic::AbcGeom::IC4fGeomParam;
37 using Alembic::AbcGeom::ICompoundProperty;
38 using Alembic::AbcGeom::ICurves;
39 using Alembic::AbcGeom::ICurvesSchema;
40 using Alembic::AbcGeom::IFaceSet;
41 using Alembic::AbcGeom::IFaceSetSchema;
42 using Alembic::AbcGeom::IGeomBaseSchema;
43 using Alembic::AbcGeom::IN3fGeomParam;
44 using Alembic::AbcGeom::index_t;
45 using Alembic::AbcGeom::Int32ArraySamplePtr;
46 using Alembic::AbcGeom::IObject;
47 using Alembic::AbcGeom::IPolyMesh;
48 using Alembic::AbcGeom::IPolyMeshSchema;
49 using Alembic::AbcGeom::ISubD;
50 using Alembic::AbcGeom::ISubDSchema;
51 using Alembic::AbcGeom::IV2fGeomParam;
52 using Alembic::AbcGeom::IXform;
53 using Alembic::AbcGeom::IXformSchema;
54 using Alembic::AbcGeom::M44d;
55 using Alembic::AbcGeom::M44f;
56 using Alembic::AbcGeom::N3fArraySamplePtr;
57 using Alembic::AbcGeom::ObjectHeader;
58 using Alembic::AbcGeom::P3fArraySamplePtr;
59 using Alembic::AbcGeom::UInt32ArraySamplePtr;
60 using Alembic::AbcGeom::V2fArraySamplePtr;
61 using Alembic::AbcMaterial::IMaterial;
62 using Alembic::AbcMaterial::IMaterialSchema;
63
dumpAttributes(T const & schema)64 template <typename T> void dumpAttributes(T const &schema) {
65
66 const size_t meshPropertyCount = schema.getNumProperties();
67
68 for (size_t p = 0; p < meshPropertyCount; p++) {
69 const PropertyHeader &header = schema.getPropertyHeader(p);
70 const PropertyType pType = header.getPropertyType();
71 const std::string &name = header.getName();
72
73 if (name == "P") {
74 schema.getNumSamples();
75 } else if (name == "uv" || name == "st") {
76 schema.getUVsParam().getNumSamples();
77 } else if (name == ".arbGeomParams") {
78 // additional geometry elements (color sets, additional texture
79 // coordinates)
80 const ICompoundProperty geoParam = schema.getArbGeomParams();
81 const size_t geoPropCount = geoParam.getNumProperties();
82
83 for (size_t g = 0; g < geoPropCount; g++) {
84 const PropertyHeader &headerGeo = geoParam.getPropertyHeader(g);
85 const std::string &nameGeo = headerGeo.getName();
86 }
87 }
88 }
89 }
90
dumpPolyMesh(const IObject & node)91 void dumpPolyMesh(const IObject &node) {
92 const ObjectHeader &header = node.getHeader();
93 const IPolyMesh mesh(node.getParent(), header.getName());
94 const IPolyMeshSchema &schema = mesh.getSchema();
95
96 // Mesh properties
97 dumpAttributes(schema);
98 }
99
dumpSubD(const IObject & node)100 void dumpSubD(const IObject &node) {
101 const ObjectHeader &header = node.getHeader();
102 const ISubD mesh(node.getParent(), header.getName());
103 const ISubDSchema &schema = mesh.getSchema();
104
105 dumpAttributes(schema);
106 schema.getSubdivisionSchemeProperty();
107 schema.getFaceVaryingInterpolateBoundaryProperty();
108 schema.getFaceVaryingPropagateCornersProperty();
109 schema.getInterpolateBoundaryProperty();
110 }
111
dumpFaceSet(const IObject & node)112 void dumpFaceSet(const IObject &node) {
113 const ObjectHeader &header = node.getHeader();
114 const IFaceSet faceSet(node.getParent(), header.getName());
115 const IFaceSetSchema &schema = faceSet.getSchema();
116 schema.getNumSamples();
117 }
118
dumpCurves(const IObject & node)119 void dumpCurves(const IObject &node) {
120 const ObjectHeader &header = node.getHeader();
121 const ICurves curves(node.getParent(), header.getName());
122 const ICurvesSchema &schema = curves.getSchema();
123
124 dumpAttributes(schema);
125 }
126
dumpXform(const IObject & node)127 void dumpXform(const IObject &node) {
128 const ObjectHeader &header = node.getHeader();
129 const IXform xform(node.getParent(), header.getName());
130 const IXformSchema &schema = xform.getSchema();
131
132 schema.getNumSamples();
133 schema.getNumOps();
134 }
135
dumpMaterial(const IObject & node)136 void dumpMaterial(const IObject &node) {
137 const ObjectHeader &header = node.getHeader();
138 IMaterial material(node.getParent(), header.getName());
139 IMaterialSchema &schema = material.getSchema();
140
141 std::vector<std::string> targetNames;
142 schema.getTargetNames(targetNames);
143
144 for (const std::string &target : targetNames) {
145 std::vector<std::string> shaderTypes;
146 schema.getShaderTypesForTarget(target, shaderTypes);
147 const size_t shaderTypeCount = shaderTypes.size();
148 for (size_t s = 0; s < shaderTypeCount; s++) {
149
150 ICompoundProperty parameters =
151 schema.getShaderParameters(target, shaderTypes[s]);
152 const size_t parameterCount = parameters.getNumProperties();
153 }
154 }
155 }
156
dumpNodes(const IObject & node)157 void dumpNodes(const IObject &node) {
158 const ObjectHeader &header = node.getHeader();
159 // Dump the general node information.
160 header.getName();
161 header.getFullName();
162 header.getMetaData().serialize();
163
164 // Dump the type specific information.
165 if (Alembic::AbcGeom::IPolyMesh::matches(header)) {
166 dumpPolyMesh(node);
167 } else if (Alembic::AbcGeom::ISubD::matches(header)) {
168 dumpSubD(node);
169 } else if (Alembic::AbcGeom::IFaceSet::matches(header)) {
170 dumpFaceSet(node);
171 } else if (Alembic::AbcGeom::ICurves::matches(header)) {
172 dumpCurves(node);
173 } else if (Alembic::AbcGeom::IXform::matches(header)) {
174 dumpXform(node);
175 } else if (Alembic::AbcMaterial::IMaterial::matches(header)) {
176 dumpMaterial(node);
177 } else { // Miscellaneous nodes such as the root.
178 ;
179 }
180
181 // Dump the child headers.
182 const size_t childCount = node.getNumChildren();
183 for (size_t i = 0; i < childCount; i++) {
184 dumpNodes(node.getChild(i));
185 }
186 }
187
dumpInfo(const char * file)188 void dumpInfo(const char *file) {
189 // Load the Alembic archive and verify that it is valid.
190 IFactory factory;
191 IArchive archive = factory.getArchive(file);
192
193 if (archive.valid()) {
194 archive.getName();
195 dumpNodes(archive.getTop());
196 }
197 }
198
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)199 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
200 FuzzerTemporaryFile tempFile(data, size);
201 dumpInfo(tempFile.filename());
202
203 return 0;
204 }
205