2019-09-13 17:06:12 +00:00
|
|
|
/*
|
|
|
|
# Copyright 2018 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.
|
|
|
|
#
|
|
|
|
################################################################################
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "jbig2.h"
|
|
|
|
|
2021-03-05 05:35:02 +00:00
|
|
|
#define ALIGNMENT ((size_t) 16)
|
|
|
|
#define KBYTE ((size_t) 1024)
|
|
|
|
#define MBYTE (1024 * KBYTE)
|
2020-02-19 16:35:51 +00:00
|
|
|
#define GBYTE (1024 * MBYTE)
|
[jbig2dec] Limit allocator to common memory use, avoiding timeouts (#6184)
The JBIG2 format allows for ridiculously large images (4G x 4G
pixels!), which means that jbig2dec may use an enormous amount of
memory when it tries to decode them. OSS-fuzz currently restricts test
cases to 2.5Gbyte of memory per run, so the jbig2dec fuzzer
implemented a custom allocator to limit jbig2dec's memory usage to
1Gbyte. When the custom allocator runs out of memory jbig2dec
indicates an error, frees its resources and returns.
Limiting memory usage to 1Gbyte, below OSS-fuzz's limit of 2.5Gbyte,
eliminated the entire class of false positive OSS-fuzz issues
concerning out of memory situations. These were false positives in the
sense that a program using jbig2dec is in control of how much memory
jbig2dec uses, but the program must implement a custom jbig2dec
allocator and limit it to the desired amount of memory.
Another class of false positive OSS-fuzz issues remain; issues where
the image data still takes more than 25 seconds to process, causing an
OSS-fuzz timeout. These cases use less than 1Gbyte of memory, but
processing that amount of data may still take a long time. Since
processing time and data size are related, a program may limit the
amount of memory allotted to jbigdec's custom allocator to something
less than 1Gbyte to reduce processing time.
Running through a set of real world JBIG2 images shows that no more
than 20MByte is used to decode any of them and none take more then 25
seconds to decode on a desktop machine. To eliminate the class of
false positive OSS-fuzz timeout issues the fuzzer will now limit the
amount of memory to 32Mbyte with the hope that their processing time
will be reduced below 25 seconds.
Of course OSS-fuzz may still detect issues where jbig2dec gets caught
in an endless loop (or the processing time is long for a reason other
than data size). These are the issues we want OSS-fuzz to identify and
get fixed, since the parameters causing those timeouts are not in
control by a program using jbig2dec.
2021-08-09 15:50:15 +00:00
|
|
|
#define MAX_ALLOCATION (32 * MBYTE)
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-05 05:35:02 +00:00
|
|
|
static size_t used;
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
static void *jbig2_fuzzer_reached_limit(size_t oldsize, size_t size)
|
2021-03-05 05:35:02 +00:00
|
|
|
{
|
2021-03-25 14:23:55 +00:00
|
|
|
if (oldsize == 0)
|
|
|
|
fprintf(stderr, "limit: %zu Mbyte used: %zu Mbyte allocation: %zu: limit reached\n", MAX_ALLOCATION / MBYTE, used / MBYTE, size);
|
|
|
|
else
|
|
|
|
fprintf(stderr, "limit: %zu Mbyte used: %zu Mbyte reallocation: %zu -> %zu: limit reached\n", MAX_ALLOCATION / MBYTE, used / MBYTE, oldsize, size);
|
|
|
|
fflush(0);
|
2021-03-05 05:35:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *jbig2_fuzzer_alloc(Jbig2Allocator *allocator, size_t size)
|
2019-09-13 17:06:12 +00:00
|
|
|
{
|
2021-03-25 14:23:55 +00:00
|
|
|
char *ptr = NULL;
|
2019-09-13 17:06:12 +00:00
|
|
|
|
|
|
|
if (size == 0)
|
|
|
|
return NULL;
|
2021-03-25 14:23:55 +00:00
|
|
|
if (size > SIZE_MAX - ALIGNMENT)
|
|
|
|
return NULL;
|
|
|
|
if (size + ALIGNMENT > MAX_ALLOCATION - used)
|
|
|
|
return jbig2_fuzzer_reached_limit(0, size + ALIGNMENT);
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
ptr = (char *) malloc(size + ALIGNMENT);
|
2020-02-19 16:35:51 +00:00
|
|
|
if (ptr == NULL)
|
2021-03-25 14:23:55 +00:00
|
|
|
return NULL;
|
2020-02-19 16:35:51 +00:00
|
|
|
|
2019-09-13 17:06:12 +00:00
|
|
|
memcpy(ptr, &size, sizeof(size));
|
2021-03-05 05:35:02 +00:00
|
|
|
used += size + ALIGNMENT;
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
return ptr + ALIGNMENT;
|
2019-09-13 17:06:12 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
static void jbig2_fuzzer_free(Jbig2Allocator *allocator, void *ptr)
|
2019-09-13 17:06:12 +00:00
|
|
|
{
|
2021-03-25 14:23:55 +00:00
|
|
|
size_t size;
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
if (ptr == NULL)
|
2019-09-13 17:06:12 +00:00
|
|
|
return;
|
2021-03-25 14:23:55 +00:00
|
|
|
if (ptr < (void *) ALIGNMENT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ptr = (char *) ptr - ALIGNMENT;
|
|
|
|
memcpy(&size, ptr, sizeof(size));
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-05 05:35:02 +00:00
|
|
|
used -= size + ALIGNMENT;
|
2021-03-25 14:23:55 +00:00
|
|
|
free(ptr);
|
2019-09-13 17:06:12 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
static void *jbig2_fuzzer_realloc(Jbig2Allocator *allocator, void *old, size_t size)
|
2019-09-13 17:06:12 +00:00
|
|
|
{
|
2021-03-25 14:23:55 +00:00
|
|
|
size_t oldsize;
|
|
|
|
char *ptr;
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
if (old == NULL)
|
|
|
|
return jbig2_fuzzer_alloc(allocator, size);
|
|
|
|
if (old < (void *) ALIGNMENT)
|
2019-09-13 17:06:12 +00:00
|
|
|
return NULL;
|
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
if (size == 0) {
|
|
|
|
jbig2_fuzzer_free(allocator, old);
|
|
|
|
return NULL;
|
2019-09-13 17:06:12 +00:00
|
|
|
}
|
2021-03-25 14:23:55 +00:00
|
|
|
if (size > SIZE_MAX - ALIGNMENT)
|
|
|
|
return NULL;
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
old = (char *) old - ALIGNMENT;
|
|
|
|
memcpy(&oldsize, old, sizeof(oldsize));
|
2020-02-19 16:35:51 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
if (size + ALIGNMENT > MAX_ALLOCATION - used + oldsize + ALIGNMENT)
|
|
|
|
return jbig2_fuzzer_reached_limit(oldsize + ALIGNMENT, size + ALIGNMENT);
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
ptr = (char *) realloc(old, size + ALIGNMENT);
|
|
|
|
if (ptr == NULL)
|
|
|
|
return NULL;
|
2019-09-13 17:06:12 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
used -= oldsize + ALIGNMENT;
|
|
|
|
memcpy(ptr, &size, sizeof(size));
|
2021-03-05 05:35:02 +00:00
|
|
|
used += size + ALIGNMENT;
|
2020-02-19 16:35:51 +00:00
|
|
|
|
2021-03-25 14:23:55 +00:00
|
|
|
return ptr + ALIGNMENT;
|
2019-09-13 17:06:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|
|
|
Jbig2Allocator allocator;
|
|
|
|
Jbig2Ctx *ctx = NULL;
|
|
|
|
|
2021-03-05 05:35:02 +00:00
|
|
|
used = 0;
|
|
|
|
|
|
|
|
allocator.alloc = jbig2_fuzzer_alloc;
|
|
|
|
allocator.free = jbig2_fuzzer_free;
|
|
|
|
allocator.realloc = jbig2_fuzzer_realloc;
|
2019-09-13 17:06:12 +00:00
|
|
|
|
|
|
|
ctx = jbig2_ctx_new(&allocator, (Jbig2Options) 0, NULL, NULL, NULL);
|
|
|
|
if (jbig2_data_in(ctx, data, size) == 0)
|
|
|
|
{
|
|
|
|
if (jbig2_complete_page(ctx) == 0)
|
|
|
|
{
|
|
|
|
Jbig2Image *image = jbig2_page_out(ctx);
|
|
|
|
if (image != NULL)
|
|
|
|
{
|
|
|
|
int sum = 0;
|
|
|
|
for (int i = 0; i < image->height * image->stride; i++)
|
|
|
|
sum += image->data[i];
|
|
|
|
printf("sum of image data bytes: %d\n", sum);
|
|
|
|
}
|
|
|
|
jbig2_release_page(ctx, image);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
jbig2_ctx_free(ctx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|