mirror of https://github.com/google/oss-fuzz.git
197 lines
5.1 KiB
C++
197 lines
5.1 KiB
C++
![]() |
// 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 <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include <ImfArray.h>
|
||
|
#include <ImfTiledRgbaFile.h>
|
||
|
|
||
|
// Handle the case when the custom namespace is not exposed
|
||
|
#include <ImfChannelList.h>
|
||
|
#include <ImfMultiPartInputFile.h>
|
||
|
#include <ImfMultiPartOutputFile.h>
|
||
|
#include <ImfPartType.h>
|
||
|
#include <ImfTiledInputPart.h>
|
||
|
#include <ImfTiledOutputPart.h>
|
||
|
#include <OpenEXRConfig.h>
|
||
|
|
||
|
using namespace OPENEXR_IMF_INTERNAL_NAMESPACE;
|
||
|
using IMATH_NAMESPACE::Box2i;
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
void readImageONE(TiledRgbaInputFile *in, int dwx, int dwy) {
|
||
|
try {
|
||
|
const Box2i &dw = in->dataWindow();
|
||
|
|
||
|
int w = dw.max.x - dw.min.x + 1;
|
||
|
int h = dw.max.y - dw.min.y + 1;
|
||
|
|
||
|
Array2D<Rgba> pixels(h, w);
|
||
|
in->setFrameBuffer(&pixels[-dwy][-dwx], 1, w);
|
||
|
in->readTiles(0, in->numXTiles() - 1, 0, in->numYTiles() - 1);
|
||
|
} catch (...) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void readImageONE2(const char fileName[]) {
|
||
|
MultiPartInputFile *in;
|
||
|
try {
|
||
|
in = new MultiPartInputFile(fileName);
|
||
|
} catch (...) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TiledInputPart *inpart;
|
||
|
try {
|
||
|
for (int p = 0; p < in->parts(); p++) {
|
||
|
try {
|
||
|
inpart = new TiledInputPart(*in, p);
|
||
|
} catch (...) {
|
||
|
inpart = NULL;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
const Box2i &dw = inpart->header().dataWindow();
|
||
|
|
||
|
int w = dw.max.x - dw.min.x + 1;
|
||
|
int h = dw.max.y - dw.min.y + 1;
|
||
|
int dwx = dw.min.x;
|
||
|
int dwy = dw.min.y;
|
||
|
|
||
|
Array2D<Rgba> pixels(h, w);
|
||
|
FrameBuffer i;
|
||
|
i.insert("R", Slice(HALF, (char *)&(pixels[-dwy][-dwx].r), sizeof(Rgba),
|
||
|
w * sizeof(Rgba)));
|
||
|
i.insert("G", Slice(HALF, (char *)&(pixels[-dwy][-dwx].g), sizeof(Rgba),
|
||
|
w * sizeof(Rgba)));
|
||
|
i.insert("B", Slice(HALF, (char *)&(pixels[-dwy][-dwx].b), sizeof(Rgba),
|
||
|
w * sizeof(Rgba)));
|
||
|
i.insert("A", Slice(HALF, (char *)&(pixels[-dwy][-dwx].a), sizeof(Rgba),
|
||
|
w * sizeof(Rgba)));
|
||
|
|
||
|
inpart->setFrameBuffer(i);
|
||
|
inpart->readTiles(0, inpart->numXTiles() - 1, 0, inpart->numYTiles() - 1);
|
||
|
|
||
|
delete inpart;
|
||
|
inpart = NULL;
|
||
|
}
|
||
|
} catch (...) {
|
||
|
delete inpart;
|
||
|
}
|
||
|
|
||
|
delete in;
|
||
|
}
|
||
|
|
||
|
void readImageMIP(TiledRgbaInputFile *in, int dwx, int dwy) {
|
||
|
try {
|
||
|
int numLevels = in->numLevels();
|
||
|
Array<Array2D<Rgba> > levels2(numLevels);
|
||
|
|
||
|
for (int level = 0; level < numLevels; ++level) {
|
||
|
int levelWidth = in->levelWidth(level);
|
||
|
int levelHeight = in->levelHeight(level);
|
||
|
levels2[level].resizeErase(levelHeight, levelWidth);
|
||
|
|
||
|
in->setFrameBuffer(&(levels2[level])[-dwy][-dwx], 1, levelWidth);
|
||
|
in->readTiles(0, in->numXTiles(level) - 1, 0, in->numYTiles(level) - 1,
|
||
|
level);
|
||
|
}
|
||
|
} catch (...) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void readImageRIP(TiledRgbaInputFile *in, int dwx, int dwy) {
|
||
|
try {
|
||
|
int numXLevels = in->numXLevels();
|
||
|
int numYLevels = in->numYLevels();
|
||
|
Array2D<Array2D<Rgba> > levels2(numYLevels, numXLevels);
|
||
|
|
||
|
for (int ylevel = 0; ylevel < numYLevels; ++ylevel) {
|
||
|
for (int xlevel = 0; xlevel < numXLevels; ++xlevel) {
|
||
|
int levelWidth = in->levelWidth(xlevel);
|
||
|
int levelHeight = in->levelHeight(ylevel);
|
||
|
levels2[ylevel][xlevel].resizeErase(levelHeight, levelWidth);
|
||
|
in->setFrameBuffer(&(levels2[ylevel][xlevel])[-dwy][-dwx], 1,
|
||
|
levelWidth);
|
||
|
|
||
|
in->readTiles(0, in->numXTiles(xlevel) - 1, 0,
|
||
|
in->numYTiles(ylevel) - 1, xlevel, ylevel);
|
||
|
}
|
||
|
}
|
||
|
} catch (...) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
static void fuzzImage(const char filename[]) {
|
||
|
Header::setMaxImageSize(10000, 10000);
|
||
|
Header::setMaxTileSize(10000, 10000);
|
||
|
|
||
|
TiledRgbaInputFile *in;
|
||
|
try {
|
||
|
in = new TiledRgbaInputFile(filename);
|
||
|
} catch (...) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const Box2i &dw = in->dataWindow();
|
||
|
int dwx = dw.min.x;
|
||
|
int dwy = dw.min.y;
|
||
|
|
||
|
readImageMIP(in, dwx, dwy);
|
||
|
readImageRIP(in, dwx, dwy);
|
||
|
readImageONE(in, dwx, dwy);
|
||
|
readImageONE2(filename);
|
||
|
|
||
|
delete in;
|
||
|
}
|
||
|
|
||
|
// from cl/164883104
|
||
|
static char *buf_to_file(const char *buf, size_t size) {
|
||
|
char *name = strdup("/dev/shm/fuzz-XXXXXX");
|
||
|
int fd = mkstemp(name);
|
||
|
if (fd < 0) {
|
||
|
perror("open");
|
||
|
exit(1);
|
||
|
}
|
||
|
size_t pos = 0;
|
||
|
while (pos < size) {
|
||
|
int nbytes = write(fd, &buf[pos], size - pos);
|
||
|
if (nbytes <= 0) {
|
||
|
perror("write");
|
||
|
exit(1);
|
||
|
}
|
||
|
pos += nbytes;
|
||
|
}
|
||
|
if (close(fd) != 0) {
|
||
|
perror("close");
|
||
|
exit(1);
|
||
|
}
|
||
|
return name;
|
||
|
}
|
||
|
|
||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||
|
char *file = buf_to_file((const char *)data, size);
|
||
|
fuzzImage(file);
|
||
|
unlink(file);
|
||
|
free(file);
|
||
|
return 0;
|
||
|
}
|