[HarfBuzz] harfbuzz: Branch 'master' - 5 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Tue Jun 26 18:44:22 UTC 2018
.circleci/config.yml | 6
src/hb-blob.cc | 152 ++++------
test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750092395970560 |binary
test/subset/run-tests.py | 101 +++---
util/options.cc | 27 -
5 files changed, 134 insertions(+), 152 deletions(-)
New commits:
commit 7db2e9ea38329b9393c9e8cc905b180735c9b0f4
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date: Tue Jun 26 10:46:10 2018 +0430
Minor on hb_blob_create_from_file
Add one more "unlikely" annotation and use explicit nullptr check for more consistency.
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 37a6d8cb..155c2e6b 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -597,7 +597,7 @@ fail_without_close:
int len = 0;
int allocated = BUFSIZ * 16;
char *blob = (char *) malloc (allocated);
- if (blob == nullptr) return hb_blob_get_empty ();
+ if (unlikely (blob == nullptr)) return hb_blob_get_empty ();
FILE *fp = fopen (file_name, "rb");
if (unlikely (fp == nullptr)) goto fread_fail_without_close;
@@ -611,7 +611,7 @@ fail_without_close:
// can cover files like that but lets limit our fallback reader
if (unlikely (allocated > 200000000)) goto fread_fail;
char *new_blob = (char *) realloc (blob, allocated);
- if (unlikely (!new_blob)) goto fread_fail;
+ if (unlikely (new_blob == nullptr)) goto fread_fail;
blob = new_blob;
}
commit 4f8753464ae44dfb60bee81ede10448175db7b90
Author: Garret Rieger <grieger at google.com>
Date: Fri Jun 22 15:29:34 2018 -0700
[subset] Add fuzzer test case that caused a timeout to the corpus.
diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750092395970560 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750092395970560
new file mode 100644
index 00000000..d622c256
Binary files /dev/null and b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5750092395970560 differ
commit 35ce8f31d37cf7c2a1f8265d36ba4c2c9a3efb2c
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date: Mon Jun 25 22:23:43 2018 +0430
Unify our pipe reader with the fallback reader (#1068)
And assign one bot to use the path always using NOMMAPFILEREADER token.
It's limited to 200mb so no more fun with using /dev/zero on hb-view!
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 55820005..de130b50 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -40,14 +40,14 @@ jobs:
- run: rm -rf harfbuzz-*
- run: make distdir && cd harfbuzz-* && cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild && CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test && ninja -Cbuild install
- alpine-O3:
+ alpine-O3-NOMMAP:
docker:
- image: alpine
steps:
- checkout
- run: apk update && apk add ragel make pkgconfig libtool autoconf automake gettext gcc g++ glib-dev freetype-dev cairo-dev
# C??FLAGS are not needed for a regular build
- - run: CFLAGS="-O3" CXXFLAGS="-O3" ./autogen.sh
+ - run: CFLAGS="-O3" CXXFLAGS="-O3 -DNOMMAPFILEREADER" ./autogen.sh
- run: make
- run: make check || .ci/fail.sh
@@ -196,7 +196,7 @@ workflows:
- distcheck
# autotools based builds
- - alpine-O3
+ - alpine-O3-NOMMAP
- archlinux-debug-O0-py3
- clang-O3-O0
- fedora-outoftreebuild
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 77dbc715..37a6d8cb 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -499,36 +499,6 @@ hb_blob_t::try_make_writable (void)
# define MAP_NORESERVE 0
#endif
-static hb_blob_t *
-_fread_to_end (FILE *file)
-{
- int allocated = BUFSIZ * 16;
- char *blob = (char *) malloc (allocated);
- if (blob == nullptr) return hb_blob_get_empty ();
-
- int len = 0;
- while (!feof (file))
- {
- if (allocated - len < BUFSIZ)
- {
- allocated *= 2;
- char *new_blob = (char *) realloc (blob, allocated);
- if (unlikely (!new_blob)) goto fail;
- blob = new_blob;
- }
-
- len += fread (blob + len, 1, allocated - len, file);
- if (ferror (file)) goto fail;
- }
-
- return hb_blob_create (blob, len, HB_MEMORY_MODE_WRITABLE, blob,
- (hb_destroy_func_t) free);
-
-fail:
- free (blob);
- return hb_blob_get_empty ();
-}
-
struct hb_mapped_file_t
{
char *contents;
@@ -547,7 +517,7 @@ _hb_mapped_file_destroy (hb_mapped_file_t *file)
UnmapViewOfFile (file->contents);
CloseHandle (file->mapping);
#else
- free (file->contents);
+ assert (0); // If we don't have mmap we shouldn't reach here
#endif
free (file);
@@ -566,87 +536,95 @@ hb_blob_create_from_file (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.
- bool writable = false;
- hb_memory_mode_t mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
+#if defined(HAVE_MMAP) && !defined(NOMMAPFILEREADER)
hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
if (unlikely (!file)) return hb_blob_get_empty ();
-#ifdef HAVE_MMAP
- int fd = open (file_name, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
-# define CLOSE close
+ int fd = open (file_name, O_RDONLY | _O_BINARY, 0);
if (unlikely (fd == -1)) goto fail_without_close;
struct stat st;
if (unlikely (fstat (fd, &st) == -1)) goto fail;
- // See https://github.com/GNOME/glib/blob/f9faac7/glib/gmappedfile.c#L139-L142
- if (unlikely (st.st_size == 0 && S_ISREG (st.st_mode))) goto fail;
-
file->length = (unsigned long) st.st_size;
- file->contents = (char *) mmap (nullptr, file->length,
- writable ? PROT_READ|PROT_WRITE : PROT_READ,
+ file->contents = (char *) mmap (nullptr, file->length, PROT_READ,
MAP_PRIVATE | MAP_NORESERVE, fd, 0);
- if (unlikely (file->contents == MAP_FAILED))
- {
- free (file);
- FILE *f = fdopen (fd, "rb");
- if (unlikely (f == nullptr))
- {
- CLOSE (fd);
- return hb_blob_get_empty ();
- }
- hb_blob_t *blob = _fread_to_end (f);
- fclose (f);
- return blob;
- }
+ if (unlikely (file->contents == MAP_FAILED)) goto fail;
-#elif defined(_WIN32) || defined(__CYGWIN__)
- HANDLE fd = CreateFile (file_name,
- writable ? GENERIC_READ|GENERIC_WRITE : GENERIC_READ,
- FILE_SHARE_READ, nullptr, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr);
-# define CLOSE CloseHandle
+ close (fd);
+
+ return hb_blob_create (file->contents, file->length,
+ HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
+ (hb_destroy_func_t) _hb_mapped_file_destroy);
+
+fail:
+ close (fd);
+fail_without_close:
+ free (file);
+
+#elif (defined(_WIN32) || defined(__CYGWIN__)) && !defined(NOMMAPFILEREADER)
+ hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
+ if (unlikely (!file)) return hb_blob_get_empty ();
+
+ HANDLE fd = CreateFile (file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
+ nullptr);
if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
file->length = (unsigned long) GetFileSize (fd, nullptr);
- file->mapping = CreateFileMapping (fd, nullptr,
- writable ? PAGE_WRITECOPY : PAGE_READONLY,
- 0, 0, nullptr);
+ file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr);
if (unlikely (file->mapping == nullptr)) goto fail;
- file->contents = (char *) MapViewOfFile (file->mapping,
- writable ? FILE_MAP_COPY : FILE_MAP_READ,
- 0, 0, 0);
+ file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
if (unlikely (file->contents == nullptr)) goto fail;
-#else
- mm = HB_MEMORY_MODE_WRITABLE;
+ CloseHandle (fd);
+ return hb_blob_create (file->contents, file->length,
+ HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
+ (hb_destroy_func_t) _hb_mapped_file_destroy);
- FILE *fd = fopen (file_name, "rb");
-# define CLOSE fclose
- if (unlikely (!fd)) goto fail_without_close;
+fail:
+ CloseHandle (fd);
+fail_without_close:
+ free (file);
+
+#endif
+
+ // The following tries to read a file without knowing its size beforehand
+ // It's used for systems without mmap concept or to read from pipes
+ int len = 0;
+ int allocated = BUFSIZ * 16;
+ char *blob = (char *) malloc (allocated);
+ if (blob == nullptr) return hb_blob_get_empty ();
- fseek (fd, 0, SEEK_END);
- file->length = ftell (fd);
- rewind (fd);
- file->contents = (char *) malloc (file->length);
- if (unlikely (!file->contents)) goto fail;
+ FILE *fp = fopen (file_name, "rb");
+ if (unlikely (fp == nullptr)) goto fread_fail_without_close;
- if (unlikely (fread (file->contents, 1, file->length, fd) != file->length))
- goto fail;
+ while (!feof (fp))
+ {
+ if (allocated - len < BUFSIZ)
+ {
+ allocated *= 2;
+ // Don't allocate more than 200MB, our mmap reader still
+ // can cover files like that but lets limit our fallback reader
+ if (unlikely (allocated > 200000000)) goto fread_fail;
+ char *new_blob = (char *) realloc (blob, allocated);
+ if (unlikely (!new_blob)) goto fread_fail;
+ blob = new_blob;
+ }
-#endif
+ len += fread (blob + len, 1, allocated - len, fp);
+ if (unlikely (ferror (fp))) goto fread_fail;
+ }
- CLOSE (fd);
- return hb_blob_create (file->contents, file->length, mm, (void *) file,
- (hb_destroy_func_t) _hb_mapped_file_destroy);
+ return hb_blob_create (blob, len, HB_MEMORY_MODE_WRITABLE, blob,
+ (hb_destroy_func_t) free);
-fail:
- CLOSE (fd);
-#undef CLOSE
-fail_without_close:
- free (file);
+fread_fail:
+ fclose (fp);
+fread_fail_without_close:
+ free (blob);
return hb_blob_get_empty ();
}
commit f57804a8a596e88843ddc8b88afac7526349b89b
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date: Mon Jun 25 18:45:49 2018 +0430
Resolve ttx absolute path before use (#1075)
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index 1cd1a19f..bc0d082e 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -15,75 +15,94 @@ import tempfile
from subset_test_suite import SubsetTestSuite
+# https://stackoverflow.com/a/377028
+def which(program):
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+ fpath, _ = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+
+ return None
+
+ttx = which ("ttx")
+ots_sanitize = which ("ots-sanitize")
+
+if not ttx:
+ print("TTX is not present, skipping test.")
+ sys.exit (77)
def cmd(command):
p = subprocess.Popen (
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdoutdata, stderrdata) = p.communicate()
+ (stdoutdata, stderrdata) = p.communicate ()
print (stderrdata, end="") # file=sys.stderr
return stdoutdata, p.returncode
-def read_binary(file_path):
- with open(file_path, 'rb') as f:
- return f.read()
+def read_binary (file_path):
+ with open (file_path, 'rb') as f:
+ return f.read ()
def fail_test(test, cli_args, message):
print ('ERROR: %s' % message)
print ('Test State:')
- print (' test.font_path %s' % os.path.abspath(test.font_path))
- print (' test.profile_path %s' % os.path.abspath(test.profile_path))
- print (' test.unicodes %s' % test.unicodes())
- expected_file = os.path.join(test_suite.get_output_directory(),
- test.get_font_name())
- print (' expected_file %s' % os.path.abspath(expected_file))
+ print (' test.font_path %s' % os.path.abspath (test.font_path))
+ print (' test.profile_path %s' % os.path.abspath (test.profile_path))
+ print (' test.unicodes %s' % test.unicodes ())
+ expected_file = os.path.join(test_suite.get_output_directory (),
+ test.get_font_name ())
+ print (' expected_file %s' % os.path.abspath (expected_file))
return 1
def run_test(test, should_check_ots):
- out_file = os.path.join(tempfile.mkdtemp(), test.get_font_name() + '-subset.ttf')
+ out_file = os.path.join(tempfile.mkdtemp (), test.get_font_name () + '-subset.ttf')
cli_args = [hb_subset,
"--font-file=" + test.font_path,
"--output-file=" + out_file,
- "--unicodes=%s" % test.unicodes()]
- cli_args.extend (test.get_profile_flags())
- print (' '.join(cli_args))
- _, return_code = cmd(cli_args)
+ "--unicodes=%s" % test.unicodes ()]
+ cli_args.extend (test.get_profile_flags ())
+ print (' '.join (cli_args))
+ _, return_code = cmd (cli_args)
if return_code:
- return fail_test(test, cli_args, "%s returned %d" % (' '.join(cli_args), return_code))
+ return fail_test (test, cli_args, "%s returned %d" % (' '.join (cli_args), return_code))
- expected_ttx, return_code = run_ttx(os.path.join(test_suite.get_output_directory(),
- test.get_font_name()))
+ expected_ttx, return_code = run_ttx (os.path.join (test_suite.get_output_directory (),
+ test.get_font_name ()))
if return_code:
- return fail_test(test, cli_args, "ttx (expected) returned %d" % (return_code))
+ return fail_test (test, cli_args, "ttx (expected) returned %d" % (return_code))
actual_ttx, return_code = run_ttx(out_file)
if return_code:
- return fail_test(test, cli_args, "ttx (actual) returned %d" % (return_code))
+ return fail_test (test, cli_args, "ttx (actual) returned %d" % (return_code))
print ("stripping checksums.")
expected_ttx = strip_check_sum (expected_ttx)
actual_ttx = strip_check_sum (actual_ttx)
if not actual_ttx == expected_ttx:
- for line in unified_diff(expected_ttx.splitlines(1), actual_ttx.splitlines(1)):
- sys.stdout.write(line)
- sys.stdout.flush()
+ for line in unified_diff (expected_ttx.splitlines (1), actual_ttx.splitlines (1)):
+ sys.stdout.write (line)
+ sys.stdout.flush ()
return fail_test(test, cli_args, 'ttx for expected and actual does not match.')
if should_check_ots:
print ("Checking output with ots-sanitize.")
- if not check_ots(out_file):
- return fail_test(test, cli_args, 'ots for subsetted file fails.')
+ if not check_ots (out_file):
+ return fail_test (test, cli_args, 'ots for subsetted file fails.')
return 0
-def run_ttx(file):
+def run_ttx (file):
print ("ttx %s" % file)
- cli_args = ["ttx",
- "-q",
- "-o-",
- file]
- return cmd(cli_args)
+ return cmd([ttx, "-q", "-o-", file])
def strip_check_sum (ttx_string):
return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]',
@@ -91,14 +110,13 @@ def strip_check_sum (ttx_string):
ttx_string.decode (), count=1)
def has_ots ():
- _, returncode = cmd(["which", "ots-sanitize"])
- if returncode:
+ if not ots_sanitize:
print("OTS is not present, skipping all ots checks.")
return False
return True
def check_ots (path):
- ots_report, returncode = cmd(["ots-sanitize", path])
+ ots_report, returncode = cmd ([ots_sanitize, path])
if returncode:
print("OTS Failure: %s" % ots_report);
return False
@@ -110,24 +128,19 @@ if not args or sys.argv[1].find('hb-subset') == -1 or not os.path.exists (sys.ar
sys.exit (1)
hb_subset, args = args[0], args[1:]
-if not len(args):
+if not len (args):
print ("No tests supplied.")
sys.exit (1)
-_, returncode = cmd(["which", "ttx"])
-if returncode:
- print("TTX is not present, skipping test.")
- sys.exit (77)
-
has_ots = has_ots()
fails = 0
for path in args:
- with io.open(path, mode="r", encoding="utf-8") as f:
+ with io.open (path, mode="r", encoding="utf-8") as f:
print ("Running tests in " + path)
- test_suite = SubsetTestSuite(path, f.read())
- for test in test_suite.tests():
- fails += run_test(test, has_ots)
+ test_suite = SubsetTestSuite (path, f.read())
+ for test in test_suite.tests ():
+ fails += run_test (test, has_ots)
if fails != 0:
print (str (fails) + " test(s) failed.")
commit 159ddb872986f121818e816d2ea75d271075ba1f
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date: Sun Jun 24 23:09:16 2018 +0430
Treat - just as /dev/stdin and remove one extra file reader (#1065)
diff --git a/util/options.cc b/util/options.cc
index 682e40c4..57cc4aa8 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -647,29 +647,20 @@ font_options_t::get_font (void) const
if (!font_file)
fail (true, "No font file set");
- if (0 == strcmp (font_file, "-")) {
- /* read it */
- GString *gs = g_string_new (nullptr);
- char buf[BUFSIZ];
+ const char *font_path = font_file;
+
+ if (0 == strcmp (font_path, "-"))
+ {
#if defined(_WIN32) || defined(__CYGWIN__)
setmode (fileno (stdin), O_BINARY);
+ font_path = "STDIN";
+#else
+ font_path = "/dev/stdin";
#endif
- while (!feof (stdin)) {
- size_t ret = fread (buf, 1, sizeof (buf), stdin);
- if (ferror (stdin))
- fail (false, "Failed reading font from standard input: %s",
- strerror (errno));
- g_string_append_len (gs, buf, ret);
- }
- unsigned int len = gs->len;
- char *font_data = g_string_free (gs, false);
- blob = hb_blob_create (font_data, len,
- HB_MEMORY_MODE_WRITABLE, font_data,
- (hb_destroy_func_t) g_free);
- } else {
- blob = hb_blob_create_from_file (font_file);
}
+ blob = hb_blob_create_from_file (font_path);
+
if (blob == hb_blob_get_empty ())
fail (false, "No such file or directory");
More information about the HarfBuzz
mailing list