[blob] Add failing versions of create API
Fixes https://github.com/harfbuzz/harfbuzz/issues/2567 New API: +hb_blob_create_or_fail() +hb_blob_create_from_file_or_fail() Use these in util/ to distinguish empty file from not-found file. Only err on the latter.
This commit is contained in:
parent
2fc8d0e6f0
commit
bdfed8f113
|
@ -21,7 +21,9 @@ hb_aat_layout_has_tracking
|
|||
<SECTION>
|
||||
<FILE>hb-blob</FILE>
|
||||
hb_blob_create
|
||||
hb_blob_create_or_fail
|
||||
hb_blob_create_from_file
|
||||
hb_blob_create_from_file_or_fail
|
||||
hb_blob_create_sub_blob
|
||||
hb_blob_copy_writable_or_fail
|
||||
hb_blob_destroy
|
||||
|
|
|
@ -241,7 +241,7 @@
|
|||
</listitem>
|
||||
</orderedlist>
|
||||
<programlisting language="C">
|
||||
hb_blob_t *blob = hb_blob_create_from_file(filename);
|
||||
hb_blob_t *blob = hb_blob_create_from_file(filename); /* or hb_blob_create_from_file_or_fail() */
|
||||
hb_face_t *face = hb_face_create(blob, 0);
|
||||
hb_font_t *font = hb_font_create(face);
|
||||
</programlisting>
|
||||
|
|
|
@ -58,8 +58,8 @@ static void draw (benchmark::State &state, const char *font_path, bool is_var, b
|
|||
hb_font_t *font;
|
||||
unsigned num_glyphs;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file (font_path);
|
||||
assert (hb_blob_get_length (blob));
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (font_path);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
num_glyphs = hb_face_get_glyph_count (face);
|
||||
|
|
|
@ -13,8 +13,8 @@ static void extents (benchmark::State &state, const char *font_path, bool is_var
|
|||
hb_font_t *font;
|
||||
unsigned num_glyphs;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file (font_path);
|
||||
assert (hb_blob_get_length (blob));
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (font_path);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
num_glyphs = hb_face_get_glyph_count (face);
|
||||
|
|
|
@ -8,18 +8,18 @@ static void shape (benchmark::State &state, const char *text_path,
|
|||
{
|
||||
hb_font_t *font;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file (font_path);
|
||||
assert (hb_blob_get_length (blob));
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (font_path);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
hb_blob_t *text_blob = hb_blob_create_from_file (text_path);
|
||||
hb_blob_t *text_blob = hb_blob_create_from_file_or_fail (text_path);
|
||||
assert (text_blob);
|
||||
unsigned text_length;
|
||||
const char *text = hb_blob_get_data (text_blob, &text_length);
|
||||
assert (text_length);
|
||||
|
||||
hb_buffer_t *buf = hb_buffer_create ();
|
||||
for (auto _ : state)
|
||||
|
|
|
@ -71,15 +71,49 @@ hb_blob_create (const char *data,
|
|||
hb_memory_mode_t mode,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy)
|
||||
{
|
||||
if (!length)
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_or_fail (data, length, mode,
|
||||
user_data, destroy);
|
||||
return likely (blob) ? blob : hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_blob_create_or_fail: (skip)
|
||||
* @data: Pointer to blob data.
|
||||
* @length: Length of @data in bytes.
|
||||
* @mode: Memory mode for @data.
|
||||
* @user_data: Data parameter to pass to @destroy.
|
||||
* @destroy: (nullable): Callback to call when @data is not needed anymore.
|
||||
*
|
||||
* Creates a new "blob" object wrapping @data. The @mode parameter is used
|
||||
* to negotiate ownership and lifecycle of @data.
|
||||
*
|
||||
* Note that this function returns a freshly-allocated empty blob even if @length
|
||||
* is zero. This is in contrast to hb_blob_create(), which returns the singleton
|
||||
* empty blob (as returned by hb_blob_get_empty()) if @length is zero.
|
||||
*
|
||||
* Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy().
|
||||
*
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_blob_t *
|
||||
hb_blob_create_or_fail (const char *data,
|
||||
unsigned int length,
|
||||
hb_memory_mode_t mode,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
|
||||
if (!length ||
|
||||
length >= 1u << 31 ||
|
||||
!(blob = hb_object_create<hb_blob_t> ())) {
|
||||
if (length >= 1u << 31 ||
|
||||
!(blob = hb_object_create<hb_blob_t> ()))
|
||||
{
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return hb_blob_get_empty ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
blob->data = data;
|
||||
|
@ -91,9 +125,10 @@ hb_blob_create (const char *data,
|
|||
|
||||
if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
|
||||
blob->mode = HB_MEMORY_MODE_READONLY;
|
||||
if (!blob->try_make_writable ()) {
|
||||
if (!blob->try_make_writable ())
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
return hb_blob_get_empty ();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,12 +596,32 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
|
|||
* Creates a new blob containing the data from the
|
||||
* specified binary font file.
|
||||
*
|
||||
* Returns: An #hb_blob_t pointer with the content of the file
|
||||
* Returns: An #hb_blob_t pointer with the content of the file,
|
||||
* or hb_blob_get_empty() if failed.
|
||||
*
|
||||
* Since: 1.7.7
|
||||
**/
|
||||
hb_blob_t *
|
||||
hb_blob_create_from_file (const char *file_name)
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name);
|
||||
return likely (blob) ? blob : hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_blob_create_from_file_or_fail:
|
||||
* @file_name: A font filename
|
||||
*
|
||||
* Creates a new blob containing the data from the
|
||||
* specified binary font file.
|
||||
*
|
||||
* Returns: An #hb_blob_t pointer with the content of the file,
|
||||
* or %NULL if failed.
|
||||
*
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_blob_t *
|
||||
hb_blob_create_from_file_or_fail (const char *file_name)
|
||||
{
|
||||
/* Adopted from glib's gmappedfile.c with Matthias Clasen and
|
||||
Allison Lortie permission but changed a lot to suit our need. */
|
||||
|
@ -601,7 +656,7 @@ hb_blob_create_from_file (const char *file_name)
|
|||
|
||||
close (fd);
|
||||
|
||||
return hb_blob_create (file->contents, file->length,
|
||||
return hb_blob_create_or_fail (file->contents, file->length,
|
||||
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
|
||||
(hb_destroy_func_t) _hb_mapped_file_destroy);
|
||||
|
||||
|
@ -661,7 +716,7 @@ fail_without_close:
|
|||
if (unlikely (!file->contents)) goto fail;
|
||||
|
||||
CloseHandle (fd);
|
||||
return hb_blob_create (file->contents, file->length,
|
||||
return hb_blob_create_or_fail (file->contents, file->length,
|
||||
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
|
||||
(hb_destroy_func_t) _hb_mapped_file_destroy);
|
||||
|
||||
|
@ -676,7 +731,7 @@ fail_without_close:
|
|||
It's used as a fallback for systems without mmap or to read from pipes */
|
||||
unsigned long len = 0, allocated = BUFSIZ * 16;
|
||||
char *data = (char *) malloc (allocated);
|
||||
if (unlikely (!data)) return hb_blob_get_empty ();
|
||||
if (unlikely (!data)) return nullptr;
|
||||
|
||||
FILE *fp = fopen (file_name, "rb");
|
||||
if (unlikely (!fp)) goto fread_fail_without_close;
|
||||
|
@ -706,13 +761,13 @@ fail_without_close:
|
|||
}
|
||||
fclose (fp);
|
||||
|
||||
return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data,
|
||||
return hb_blob_create_or_fail (data, len, HB_MEMORY_MODE_WRITABLE, data,
|
||||
(hb_destroy_func_t) free);
|
||||
|
||||
fread_fail:
|
||||
fclose (fp);
|
||||
fread_fail_without_close:
|
||||
free (data);
|
||||
return hb_blob_get_empty ();
|
||||
return nullptr;
|
||||
}
|
||||
#endif /* !HB_NO_OPEN */
|
||||
|
|
|
@ -90,9 +90,19 @@ hb_blob_create (const char *data,
|
|||
void *user_data,
|
||||
hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_create_or_fail (const char *data,
|
||||
unsigned int length,
|
||||
hb_memory_mode_t mode,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_create_from_file (const char *file_name);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_blob_create_from_file_or_fail (const char *file_name);
|
||||
|
||||
/* Always creates with MEMORY_MODE_READONLY.
|
||||
* Even if the parent blob is writable, we don't
|
||||
* want the user of the sub-blob to be able to
|
||||
|
|
12
src/main.cc
12
src/main.cc
|
@ -33,12 +33,13 @@
|
|||
#include "hb.h"
|
||||
#include "hb-ot.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef HB_NO_OPEN
|
||||
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
|
||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||
#endif
|
||||
|
||||
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
|
||||
|
@ -505,7 +506,8 @@ main (int argc, char **argv)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||
assert (blob);
|
||||
printf ("Opened font file %s: %d bytes long\n", argv[1], hb_blob_get_length (blob));
|
||||
#ifndef MAIN_CC_NO_PRIVATE_API
|
||||
print_layout_info_using_private_api (blob);
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef HB_NO_OPEN
|
||||
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
|
||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -48,7 +48,8 @@ main (int argc, char **argv)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "hb-ot.h"
|
||||
|
||||
#ifdef HB_NO_OPEN
|
||||
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
|
||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -42,7 +42,8 @@ main (int argc, char **argv)
|
|||
}
|
||||
|
||||
/* Create the face */
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef HB_NO_OPEN
|
||||
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
|
||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -46,7 +46,8 @@ main (int argc, char **argv)
|
|||
}
|
||||
|
||||
/* Create the face */
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "hb-ot.h"
|
||||
|
||||
#ifdef HB_NO_OPEN
|
||||
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
|
||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -39,7 +39,8 @@ main (int argc, char **argv)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
hb_blob_destroy (blob);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "hb-ot.h"
|
||||
|
||||
#ifdef HB_NO_OPEN
|
||||
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
|
||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -37,7 +37,8 @@ main (int argc, char **argv)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "hb-ot.h"
|
||||
|
||||
#ifdef HB_NO_OPEN
|
||||
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
|
||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -39,7 +39,8 @@ main (int argc, char **argv)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef HB_NO_OPEN
|
||||
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
|
||||
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -42,7 +42,8 @@ main (int argc, char **argv)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||
assert (blob);
|
||||
printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob));
|
||||
|
||||
/* Create the face */
|
||||
|
|
|
@ -296,9 +296,9 @@ hb_test_open_font_file (const char *font_path)
|
|||
char *path = g_strdup (font_path);
|
||||
#endif
|
||||
|
||||
hb_blob_t *blob = hb_blob_create_from_file (path);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (path);
|
||||
hb_face_t *face;
|
||||
if (hb_blob_get_length (blob) == 0)
|
||||
if (!blob)
|
||||
g_error ("Font %s not found.", path);
|
||||
|
||||
face = hb_face_create (blob, 0);
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
#include "hb-fuzzer.hh"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file (argv[i]);
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[i]);
|
||||
assert (blob);
|
||||
|
||||
unsigned int len;
|
||||
unsigned len = 0;
|
||||
const char *font_data = hb_blob_get_data (blob, &len);
|
||||
printf ("%s%s\n", argv[i], len ? "" : " (note: not found or was empty)");
|
||||
printf ("%s (%u bytes)\n", argv[i], len);
|
||||
|
||||
LLVMFuzzerTestOneInput ((const uint8_t *) font_data, len);
|
||||
|
||||
|
|
|
@ -696,10 +696,10 @@ font_options_t::get_font () const
|
|||
#endif
|
||||
}
|
||||
|
||||
blob = hb_blob_create_from_file (font_path);
|
||||
blob = hb_blob_create_from_file_or_fail (font_path);
|
||||
|
||||
if (blob == hb_blob_get_empty ())
|
||||
fail (false, "Couldn't read or find %s, or it was empty.", font_path);
|
||||
if (!blob)
|
||||
fail (false, "%s: Failed reading file", font_path);
|
||||
|
||||
/* Create the face */
|
||||
hb_face_t *face = hb_face_create (blob, face_index);
|
||||
|
|
Loading…
Reference in New Issue