[fuzz] Implement failing allocator

This commit is contained in:
Ebrahim Byagowi 2020-07-14 19:29:58 +04:30
parent 44a3136ae6
commit c33e8006fd
8 changed files with 88 additions and 1 deletions

57
src/failing-alloc.c Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright © 2020 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include <stdlib.h>
#include <stdio.h>
int alloc_state = 0;
__attribute__((no_sanitize("integer")))
static int fastrand ()
{
if (!alloc_state) return 1;
/* Based on https://software.intel.com/content/www/us/en/develop/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor.html */
alloc_state = (214013 * alloc_state + 2531011);
return (alloc_state >> 16) & 0x7FFF;
}
void* hb_malloc_impl (size_t size)
{
return (fastrand () % 16) ? malloc (size) : NULL;
}
void* hb_calloc_impl (size_t nmemb, size_t size)
{
return (fastrand () % 16) ? calloc (nmemb, size) : NULL;
}
void* hb_realloc_impl (void *ptr, size_t size)
{
return (fastrand () % 16) ? realloc (ptr, size) : NULL;
}
void hb_free_impl (void *ptr)
{
return free (ptr);
}

View File

@ -397,6 +397,14 @@ else
hb_so_version = '0' hb_so_version = '0'
endif endif
if get_option('fuzzer_ldflags') != ''
extra_hb_cpp_args += ['-DHB_CUSTOM_MALLOC']
hb_sources += 'failing-alloc.c'
hb_subset_sources += 'failing-alloc.c'
hb_icu_sources += 'failing-alloc.c'
hb_gobject_sources += 'failing-alloc.c'
endif
libharfbuzz = library('harfbuzz', hb_sources, libharfbuzz = library('harfbuzz', hb_sources,
include_directories: incconfig, include_directories: incconfig,
dependencies: harfbuzz_deps, dependencies: harfbuzz_deps,

View File

@ -115,6 +115,8 @@ static void misc_calls_for_gid (hb_face_t *face, hb_font_t *font, hb_set_t *set,
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
alloc_state = size; /* see src/failing-alloc.c */
hb_blob_t *blob = hb_blob_create ((const char *) data, size, hb_blob_t *blob = hb_blob_create ((const char *) data, size,
HB_MEMORY_MODE_READONLY, nullptr, nullptr); HB_MEMORY_MODE_READONLY, nullptr, nullptr);
hb_face_t *face = hb_face_create (blob, 0); hb_face_t *face = hb_face_create (blob, 0);

View File

@ -2,3 +2,11 @@
#include <stddef.h> #include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
#ifdef HB_IS_IN_FUZZER
/* See src/failing-alloc.c */
extern "C" int alloc_state;
#else
/* Just a dummy global variable */
static int alloc_state = 0;
#endif

View File

@ -32,6 +32,8 @@ static hb_set_t *create_set (const uint32_t *value_array, int count)
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{ {
alloc_state = size; /* see src/failing-alloc.c */
if (size < sizeof (instructions_t)) if (size < sizeof (instructions_t))
return 0; return 0;

View File

@ -33,7 +33,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
hb_buffer_t *buffer = hb_buffer_create (); hb_buffer_t *buffer = hb_buffer_create ();
hb_buffer_add_utf8 (buffer, text, -1, 0, -1); hb_buffer_add_utf8 (buffer, text, -1, 0, -1);
hb_buffer_guess_segment_properties (buffer); hb_buffer_guess_segment_properties (buffer);
alloc_state = size; /* see src/failing-alloc.c TODO: move to top */
hb_shape (font, buffer, nullptr, 0); hb_shape (font, buffer, nullptr, 0);
alloc_state = 0; /* no failing alloc, TODO: remove */
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
} }
@ -45,12 +47,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
memcpy (text32, data + size - len, len); memcpy (text32, data + size - len, len);
/* Misc calls on font. */ /* Misc calls on font. */
alloc_state = size; /* see src/failing-alloc.c TODO: move to top */
text32[10] = test_font (font, text32[15]) % 256; text32[10] = test_font (font, text32[15]) % 256;
alloc_state = 0; /* no failing alloc, TODO: remove */
hb_buffer_t *buffer = hb_buffer_create (); hb_buffer_t *buffer = hb_buffer_create ();
hb_buffer_add_utf32 (buffer, text32, sizeof (text32) / sizeof (text32[0]), 0, -1); hb_buffer_add_utf32 (buffer, text32, sizeof (text32) / sizeof (text32[0]), 0, -1);
hb_buffer_guess_segment_properties (buffer); hb_buffer_guess_segment_properties (buffer);
alloc_state = size; /* see src/failing-alloc.c TODO: move to top */
hb_shape (font, buffer, nullptr, 0); hb_shape (font, buffer, nullptr, 0);
alloc_state = 0; /* no failing alloc, TODO: remove */
hb_buffer_destroy (buffer); hb_buffer_destroy (buffer);
hb_font_destroy (font); hb_font_destroy (font);

View File

@ -67,6 +67,8 @@ trySubset (hb_face_t *face,
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
alloc_state = size; /* see src/failing-alloc.c */
hb_blob_t *blob = hb_blob_create ((const char *)data, size, hb_blob_t *blob = hb_blob_create ((const char *)data, size,
HB_MEMORY_MODE_READONLY, nullptr, nullptr); HB_MEMORY_MODE_READONLY, nullptr, nullptr);
hb_face_t *face = hb_face_create (blob, 0); hb_face_t *face = hb_face_create (blob, 0);

View File

@ -10,15 +10,17 @@ foreach file_name : tests
sources = [file_name] sources = [file_name]
fuzzer_ldflags = [] fuzzer_ldflags = []
extra_cpp_args = []
if get_option('fuzzer_ldflags') == '' if get_option('fuzzer_ldflags') == ''
sources += 'main.cc' sources += 'main.cc'
else else
fuzzer_ldflags += get_option('fuzzer_ldflags').split() fuzzer_ldflags += get_option('fuzzer_ldflags').split()
extra_cpp_args += '-DHB_IS_IN_FUZZER'
endif endif
exe = executable(test_name, sources, exe = executable(test_name, sources,
cpp_args: cpp_args, cpp_args: cpp_args + extra_cpp_args,
include_directories: [incconfig, incsrc], include_directories: [incconfig, incsrc],
link_args: fuzzer_ldflags, link_args: fuzzer_ldflags,
link_with: [libharfbuzz, libharfbuzz_subset], link_with: [libharfbuzz, libharfbuzz_subset],