From e3a36262482e58e51fa4a16c51a599be89ec7a46 Mon Sep 17 00:00:00 2001 From: "yusukes@chromium.org" Date: Thu, 3 Dec 2009 10:25:32 +0000 Subject: [PATCH] Upload test scripts for ots which I'm currently using. - test_unmalicious_fonts.sh Apply ots/test/idempotent to all TT/OT files under $BASEDIR in order to verify that: * OTS does not reject unmalicious fonts. * The new font OTS generates can be loaded by a system font renderer. - test_malicious_fonts.sh Apply ots/test/validator-checker to all malicious TT/OT files in order to verify that OTS can reject malicious fonts, or the "sanitized" font generated by OTS does not crash a system font renderer. - test/validator-checker.cc Add Mac support. - test/idempotent.cc Add Mac and FreeType2 support. Example output: yusukes@z-yusukes-jp:~/chromium/src/third_party/ots/test$ ./test_unmalicious_fonts.sh ................ FAIL: /usr/share/fonts/truetype/ttf-oriya-fonts/Samyak-Oriya.ttf (Run ./idempotent /usr/share/fonts/truetype/ttf-oriya-fonts/Samyak-Oriya.ttf for more information.) ........ yusukes@z-yusukes-jp:~/chromium/src/third_party/ots/test$ Review URL: http://codereview.chromium.org/408020 BUG=27139 TEST=see http://code.google.com/p/ots/wiki/HowToTestOts TBR=jshin --- test/BLACKLIST.txt | 123 +++++++++++++++++++++++++++++++++ test/SConstruct | 2 +- test/idempotent.cc | 69 ++++++++++++++++++ test/test_malicious_fonts.sh | 39 +++++++++++ test/test_unmalicious_fonts.sh | 50 ++++++++++++++ test/validator-checker.cc | 92 ++++++++++++++++++++---- 6 files changed, 361 insertions(+), 14 deletions(-) create mode 100644 test/BLACKLIST.txt create mode 100644 test/test_malicious_fonts.sh create mode 100644 test/test_unmalicious_fonts.sh diff --git a/test/BLACKLIST.txt b/test/BLACKLIST.txt new file mode 100644 index 00000000..475b9450 --- /dev/null +++ b/test/BLACKLIST.txt @@ -0,0 +1,123 @@ +# Required table(s) are missing (e.g. OS/2 table). +AppleGothic.ttf +AppleMyungjo.ttf +ArialHB.ttf +ArialHBBold.ttf +Corsiva.ttf +CorsivaBold.ttf +InaiMathi.ttf +NISC18030.ttf +NewPeninimMT.ttf +NewPeninimMTBold.ttf +NewPeninimMTBoldInclined.ttf +NewPeninimMTInclined.ttf +Raanana.ttf +RaananaBold.ttf + +# The length field of a table is weird. +homa.ttf +nazli.ttf +titr.ttf +ume-tgc4.ttf +ume-tgs4.ttf +ume-tgc5.ttf +ume-tgs5.ttf +ume-tms3.ttf + +# Table(s) are not 4-byte aligned. +UnBatang.ttf +UnBom.ttf +UnDotum.ttf +UnGraphic.ttf +UnGungseo.ttf +UnJamoBatang.ttf +UnJamoDotum.ttf +UnJamoNovel.ttf +UnJamoSora.ttf +UnPenheulim.ttf +UnPen.ttf +UnPilgiBold.ttf +UnPilgi.ttf +UnShinmun.ttf +UnTaza.ttf +UnYetgul.ttf + +# Tables are not sorted by table tags. +f500.ttf + +# non-ASCII characters are used in a table tag +SyrCOMAdiabene.otf +SyrCOMAntioch.otf +SyrCOMBatnanBold.otf +SyrCOMBatnan.otf +SyrCOMCtesiphon.otf +SyrCOMJerusalemBold.otf +SyrCOMJerusalemItalic.otf +SyrCOMJerusalem.otf +SyrCOMJerusalemOutline.otf +SyrCOMKharput.otf +SyrCOMMalankara.otf +SyrCOMMardinBold.otf +SyrCOMMardin.otf +SyrCOMMidyat.otf +SyrCOMNisibin.otf +SyrCOMNisibinOutline.otf +SyrCOMQenNeshrin.otf +SyrCOMTalada.otf +SyrCOMTurAbdin.otf +SyrCOMUrhoyBold.otf +SyrCOMUrhoy.otf + +# Malformed SFNT table; unexpected entry selector +misakimn.ttf +misaki.ttf + +# Malformed CMAP table; Subtables are not sorted by platform ID +ani.ttf +Caliban.ttf + +# Malformed CMAP table; Entries in a 3-0-4 or 3-1-4 subtable are not sorted. +LucidaSansOblique.ttf +LucidaTypewriterOblique.ttf +bkai00mp.ttf +bsmi00lp.ttf +modelwor.ttf + +# Malformed CMAP table; "search range" in a 3-0-4 or 3-1-4 subtable are invalid. +cmmi10.ttf +cmsy10.ttf +msam10.ttf + +# Malformed CMAP table; The 3-10-12 table is too short. +BPG_Chveulebrivi.ttf +BPG_Chveulebrivi_bold.ttf + +# Unsupported CMAP table; ots doesn't support non-Unicode fonts. +Apple Symbols.ttf +儷宋 Pro.ttf +儷黑 Pro.ttf +华文仿宋.ttf +华文宋体.ttf +华文楷体.ttf +华文细黑.ttf +华文黑体.ttf + +# Unsupported CMAP table; The Unicode BMP table is missing, while the UCS-4 table is available. +DroidSansJapanese.ttf +DroidSansFallback.ttf + +# Malformed GLYF table; The content of flags array and the lengths of xCoordinates, yCoordinates are inconsistent. +DecoTypeNaskh.ttf + +# Malformed POST table; A glyph index in the reserved area (>= 32768) is specified. +wqy-zenhei.ttf +unifont.ttf + +# Malformed HMTX table; The table is too short. +mona.ttf + +# CMAP glyph id is out of range. +Samyak-Oriya.ttf + +# Unsupported CFF table; "supplemental encoding" is not supported at the moment. This should be fixed in the future. +Walbf___.otf diff --git a/test/SConstruct b/test/SConstruct index 1f639d61..1142ab71 100644 --- a/test/SConstruct +++ b/test/SConstruct @@ -35,7 +35,7 @@ env.Library('../src/libots.a', ]) env.Program('../test/ot-sanitise.cc', LIBS = ['ots'], LIBPATH='../src') -env.Program('../test/idempotent.cc', LIBS = ['ots'], LIBPATH='../src') +env.Program('../test/idempotent.cc', LIBS = ['ots', 'freetype', 'z', 'm'], LIBPATH='../src') env.Program('../test/perf.cc', LIBS = ['ots'], LIBPATH='../src') # TODO(yusukes): better to use pkg-config freetype2 --libs diff --git a/test/idempotent.cc b/test/idempotent.cc index 7f33a47f..e0ab0fde 100644 --- a/test/idempotent.cc +++ b/test/idempotent.cc @@ -2,6 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#if !defined(_MSC_VER) +#ifdef __linux__ +// Linux +#include +#include +#include FT_FREETYPE_H +#else +// Mac OS X +#include // g++ -framework Cocoa +#endif // __linux__ +#else +// Windows +// TODO(yusukes): Support Windows. +#endif // _MSC_VER + #include #include #include @@ -90,5 +105,59 @@ int main(int argc, char **argv) { } } + // Verify that the transcoded font can be opened by the font renderer for + // Linux (FreeType2), Mac OS X, or Windows. +#if !defined(_MSC_VER) +#ifdef __linux__ + // Linux + FT_Library library; + FT_Error error = ::FT_Init_FreeType(&library); + if (error) { + std::fprintf(stderr, "Failed to initialize FreeType2!\n"); + return 1; + } + FT_Face dummy; + error = ::FT_New_Memory_Face(library, result, result_len, 0, &dummy); + if (error) { + std::fprintf(stderr, "Failed to open the transcoded font\n"); + return 1; + } +#else + // Mac OS X + ATSFontContainerRef container_ref = 0; + ATSFontActivateFromMemory(result, result_len, 3, kATSFontFormatUnspecified, + NULL, kATSOptionFlagsDefault, &container_ref); + if (!container_ref) { + std::fprintf(stderr, "Failed to open the transcoded font\n"); + return 1; + } + + ItemCount count; + ATSFontFindFromContainer( + container_ref, kATSOptionFlagsDefault, 0, NULL, &count); + if (!count) { + std::fprintf(stderr, "Failed to open the transcoded font\n"); + return 1; + } + + ATSFontRef ats_font_ref = 0; + ATSFontFindFromContainer( + container_ref, kATSOptionFlagsDefault, 1, &ats_font_ref, NULL); + if (!ats_font_ref) { + std::fprintf(stderr, "Failed to open the transcoded font\n"); + return 1; + } + + CGFontRef cg_font_ref = CGFontCreateWithPlatformFont(&ats_font_ref); + if (!CGFontGetNumberOfGlyphs(cg_font_ref)) { + std::fprintf(stderr, "Failed to open the transcoded font\n"); + return 1; + } +#endif // __linux__ +#else + // Windows + // TODO(yusukes): Support Windows. +#endif // _MSC_VER + return 0; } diff --git a/test/test_malicious_fonts.sh b/test/test_malicious_fonts.sh new file mode 100644 index 00000000..7a35f263 --- /dev/null +++ b/test/test_malicious_fonts.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Copyright (c) 2009 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Usage: ./test_malicious_fonts.sh [ttf_or_otf_file_name] + +BASE_DIR=~/malicious/ +CHECKER=./validator-checker + +if [ ! -x "$CHECKER" ] ; then + echo "$CHECKER is not found." + exit 1 +fi + +if [ $# -eq 0 ] ; then + # No font file is specified. Apply this script to all TT/OT files under the + # BASE_DIR. + if [ ! -d $BASE_DIR ] ; then + echo "$BASE_DIR does not exist." + exit 1 + fi + + # Recursively call this script. + find $BASE_DIR -type f -name '*tf' -exec "$0" {} \; + echo + exit 0 +fi + +if [ $# -gt 1 ] ; then + echo "Usage: $0 [ttf_or_otf_file_name]" + exit 1 +fi + +# Confirm that the malicious font file does not crash OTS nor OS font renderer. +base=`basename "$1"` +"$CHECKER" "$1" > /dev/null 2>&1 || (echo ; echo "\nFAIL: $1 (Run $CHECKER $1 for more information.)") +echo -n "." diff --git a/test/test_unmalicious_fonts.sh b/test/test_unmalicious_fonts.sh new file mode 100644 index 00000000..ae3a5bbd --- /dev/null +++ b/test/test_unmalicious_fonts.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Copyright (c) 2009 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Usage: ./test_unmalicious_fonts.sh [ttf_or_otf_file_name] + +BLACKLIST=./BLACKLIST.txt +CHECKER=./idempotent + +if [ ! -r "$BLACKLIST" ] ; then + echo "$BLACKLIST is not found." + exit 1 +fi + +if [ ! -x "$CHECKER" ] ; then + echo "$CHECKER is not found." + exit 1 +fi + +if [ $# -eq 0 ] ; then + # No font file is specified. Apply this script to all TT/OT files under the + # BASE_DIR below. + + # On Ubuntu Linux (>= 8.04), You can install ~1800 TrueType/OpenType fonts + # to /usr/share/fonts/truetype by: + # % sudo apt-get install ttf-.*[^0]$ + BASE_DIR=/usr/share/fonts/truetype/ + if [ ! -d $BASE_DIR ] ; then + # Mac OS X + BASE_DIR="/Library/Fonts/ /System/Library/Fonts/" + fi + # TODO(yusukes): Support Cygwin. + + # Recursively call this script. + find $BASE_DIR -type f -name '*tf' -exec "$0" {} \; + echo + exit 0 +fi + +if [ $# -gt 1 ] ; then + echo "Usage: $0 [ttf_or_otf_file_name]" + exit 1 +fi + +# Check the font file using idempotent iff the font is not blacklisted. +base=`basename "$1"` +egrep -i -e "^$base" "$BLACKLIST" > /dev/null 2>&1 || "$CHECKER" "$1" > /dev/null 2>&1 || (echo ; echo "FAIL: $1 (Run $CHECKER $1 for more information.)") +echo -n "." diff --git a/test/validator-checker.cc b/test/validator-checker.cc index e01b0fbf..1188dc75 100644 --- a/test/validator-checker.cc +++ b/test/validator-checker.cc @@ -2,9 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include +#if !defined(_MSC_VER) +#ifdef __linux__ +// Linux +#include #include #include FT_FREETYPE_H +#else +// Mac OS X +#include // g++ -framework Cocoa +#endif // __linux__ +#else +// Windows +// TODO(yusukes): Support Windows. +#endif // _MSC_VER + +#include #include #include #include @@ -18,6 +31,9 @@ namespace { +#if !defined(_MSC_VER) +#ifdef __linux__ +// Linux void LoadChar(FT_Face face, int pt, FT_ULong c) { FT_Matrix matrix; matrix.xx = matrix.yy = 1 << 16; @@ -28,11 +44,17 @@ void LoadChar(FT_Face face, int pt, FT_ULong c) { FT_Load_Char(face, c, FT_LOAD_RENDER); } -int OpenAndLoadChars(FT_Library library, const char *file_name, - uint8_t *trans_font, size_t trans_len) { +int OpenAndLoadChars( + const char *file_name, uint8_t *trans_font, size_t trans_len) { + FT_Library library; + FT_Error error = FT_Init_FreeType(&library); + if (error) { + std::fprintf(stderr, "Failed to initialize FreeType2!\n"); + return 1; + } + FT_Face trans_face; - FT_Error error - = FT_New_Memory_Face(library, trans_font, trans_len, 0, &trans_face); + error = FT_New_Memory_Face(library, trans_font, trans_len, 0, &trans_face); if (error) { std::fprintf(stderr, "OK: FreeType2 couldn't open the transcoded font: %s\n", @@ -66,6 +88,57 @@ int OpenAndLoadChars(FT_Library library, const char *file_name, std::fprintf(stderr, "OK: FreeType2 didn't crash: %s\n", file_name); return 0; } +#else +// Mac OS X +int OpenAndLoadChars( + const char *file_name, uint8_t *trans_font, size_t trans_len) { + ATSFontContainerRef container_ref = 0; + ATSFontActivateFromMemory(trans_font, trans_len, 3, kATSFontFormatUnspecified, + NULL, kATSOptionFlagsDefault, &container_ref); + if (!container_ref) { + std::fprintf(stderr, + "OK: font renderer couldn't open the transcoded font: %s\n", + file_name); + return 0; + } + + ItemCount count; + ATSFontFindFromContainer( + container_ref, kATSOptionFlagsDefault, 0, NULL, &count); + if (!count) { + std::fprintf(stderr, + "OK: font renderer couldn't open the transcoded font: %s\n", + file_name); + return 0; + } + + ATSFontRef ats_font_ref = 0; + ATSFontFindFromContainer( + container_ref, kATSOptionFlagsDefault, 1, &ats_font_ref, NULL); + if (!ats_font_ref) { + std::fprintf(stderr, + "OK: font renderer couldn't open the transcoded font: %s\n", + file_name); + return 0; + } + + CGFontRef cg_font_ref = CGFontCreateWithPlatformFont(&ats_font_ref); + if (!CGFontGetNumberOfGlyphs(cg_font_ref)) { + std::fprintf(stderr, + "OK: font renderer couldn't open the transcoded font: %s\n", + file_name); + return 0; + } + + std::fprintf(stderr, "OK: font renderer didn't crash: %s\n", file_name); + // TODO(yusukes): would be better to perform LoadChar() like Linux. + return 0; +} +#endif // __linux__ +#else +// Windows +// TODO(yusukes): Support Windows. +#endif // _MSC_VER } // namespace @@ -107,12 +180,5 @@ int main(int argc, char **argv) { } const size_t trans_len = output.Tell(); - FT_Library library; - FT_Error error = FT_Init_FreeType(&library); - if (error) { - std::fprintf(stderr, "Failed to initialize FreeType2!\n"); - return 1; - } - - return OpenAndLoadChars(library, argv[1], trans_font, trans_len); + return OpenAndLoadChars(argv[1], trans_font, trans_len); }