This source file includes following definitions.
- generate_plane
- create_image
- capacity_
- data
- write
- LLVMFuzzerTestOneInput
#include <assert.h>
#include <string.h>
#include <memory>
#include "heif.h"
static void generate_plane(int width, int height, uint8_t* output, int stride) {
if (width == stride) {
memset(output, 0, width * height);
} else {
for (int y = 0; y < height; y++) {
memset(output, 0, width);
output += stride;
}
}
}
static size_t create_image(const uint8_t* data, size_t size, struct heif_image** image) {
if (size < 2) {
return 0;
}
int width = data[0] + 16;
int height = data[1] + 16;
data += 2;
size -= 2;
heif_colorspace colorspace = heif_colorspace_YCbCr;
heif_chroma chroma = heif_chroma_420;
struct heif_error err = heif_image_create(width, height, colorspace, chroma, image);
if (err.code != heif_error_Ok) {
return 0;
}
err = heif_image_add_plane(*image, heif_channel_Y, width, height, 8);
assert(err.code == heif_error_Ok);
err = heif_image_add_plane(*image, heif_channel_Cb, width / 2, height / 2, 8);
assert(err.code == heif_error_Ok);
err = heif_image_add_plane(*image, heif_channel_Cr, width / 2, height / 2, 8);
assert(err.code == heif_error_Ok);
int stride;
uint8_t* plane;
plane = heif_image_get_plane(*image, heif_channel_Y, &stride);
generate_plane(width, height, plane, stride);
plane = heif_image_get_plane(*image, heif_channel_Cb, &stride);
generate_plane(width / 2, height / 2, plane, stride);
plane = heif_image_get_plane(*image, heif_channel_Cr, &stride);
generate_plane(width / 2, height / 2, plane, stride);
return 2;
}
class MemoryWriter {
public:
MemoryWriter() : data_(nullptr), size_(0), capacity_(0) {}
~MemoryWriter() {
free(data_);
}
const uint8_t* data() const { return data_; }
size_t size() const { return size_; }
void write(const void* data, size_t size) {
if (capacity_ - size_ < size) {
size_t new_capacity = capacity_ + size;
uint8_t* new_data = static_cast<uint8_t*>(malloc(new_capacity));
assert(new_data);
if (data_) {
memcpy(new_data, data_, size_);
free(data_);
}
data_ = new_data;
capacity_ = new_capacity;
}
memcpy(&data_[size_], data, size);
size_ += size;
}
public:
uint8_t* data_;
size_t size_;
size_t capacity_;
};
static struct heif_error writer_write(struct heif_context* ctx, const void* data, size_t size, void* userdata) {
MemoryWriter* writer = static_cast<MemoryWriter*>(userdata);
writer->write(data, size);
struct heif_error err{heif_error_Ok, heif_suberror_Unspecified, nullptr};
return err;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
struct heif_error err;
std::shared_ptr<heif_context> context(heif_context_alloc(),
[] (heif_context* c) { heif_context_free(c); });
assert(context);
static const size_t kMaxEncoders = 5;
const heif_encoder_descriptor* encoder_descriptors[kMaxEncoders];
int count = heif_context_get_encoder_descriptors(context.get(), heif_compression_HEVC, nullptr,
encoder_descriptors, kMaxEncoders);
assert(count > 0);
heif_encoder* encoder;
err = heif_context_get_encoder(context.get(), encoder_descriptors[0], &encoder);
if (err.code != heif_error_Ok) {
return 0;
}
if (size < 2) {
heif_encoder_release(encoder);
return 0;
}
int quality = data[0] % 101;;
int lossless = (data[1] > 0x80);
data += 2;
size -= 2;
heif_encoder_set_lossy_quality(encoder, quality);
heif_encoder_set_lossless(encoder, lossless);
struct heif_image* image;
size_t read = create_image(data, size, &image);
assert(read <= size);
if (!read) {
heif_encoder_release(encoder);
return 0;
}
data += read;
size -= read;
struct heif_image_handle* img;
err = heif_context_encode_image(context.get(), image, encoder, nullptr, &img);
heif_image_release(image);
heif_encoder_release(encoder);
if (err.code != heif_error_Ok) {
return 0;
}
heif_image_handle_release(img);
MemoryWriter writer;
struct heif_writer w;
w.writer_api_version = 1;
w.write = writer_write;
heif_context_write(context.get(), &w, &writer);
assert(writer.size() > 0);
return 0;
}