1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
13 #include <ApplicationServices/ApplicationServices.h> // g++ -framework Cocoa
17 // TODO(yusukes): Support Windows.
22 #include <sys/types.h>
29 #include "opentype-sanitiser.h"
30 #include "ots-memory-stream.h"
34 #if !defined(_MSC_VER)
37 void LoadChar(FT_Face face
, int pt
, FT_ULong c
) {
39 matrix
.xx
= matrix
.yy
= 1 << 16;
40 matrix
.xy
= matrix
.yx
= 0 << 16;
42 FT_Set_Char_Size(face
, pt
* (1 << 6), 0, 72, 0);
43 FT_Set_Transform(face
, &matrix
, 0);
44 FT_Load_Char(face
, c
, FT_LOAD_RENDER
);
48 const char *file_name
, uint8_t *trans_font
, size_t trans_len
) {
50 FT_Error error
= FT_Init_FreeType(&library
);
52 std::fprintf(stderr
, "Failed to initialize FreeType2!\n");
57 error
= FT_New_Memory_Face(library
, trans_font
, trans_len
, 0, &trans_face
);
60 "OK: FreeType2 couldn't open the transcoded font: %s\n",
65 static const int kPts
[] = {100, 20, 18, 16, 12, 10, 8}; // pt
66 static const size_t kPtsLen
= sizeof(kPts
) / sizeof(kPts
[0]);
68 static const int kUnicodeRanges
[] = {
69 0x0020, 0x007E, // Basic Latin (ASCII)
70 0x00A1, 0x017F, // Latin-1
71 0x1100, 0x11FF, // Hangul
72 0x3040, 0x309F, // Japanese HIRAGANA letters
73 0x3130, 0x318F, // Hangul
74 0x4E00, 0x4F00, // CJK Kanji/Hanja
75 0xAC00, 0xAD00, // Hangul
77 static const size_t kUnicodeRangesLen
78 = sizeof(kUnicodeRanges
) / sizeof(kUnicodeRanges
[0]);
80 for (size_t i
= 0; i
< kPtsLen
; ++i
) {
81 for (size_t j
= 0; j
< kUnicodeRangesLen
; j
+= 2) {
82 for (int k
= 0; k
<= kUnicodeRanges
[j
+ 1] - kUnicodeRanges
[j
]; ++k
) {
83 LoadChar(trans_face
, kPts
[i
], kUnicodeRanges
[j
] + k
);
88 std::fprintf(stderr
, "OK: FreeType2 didn't crash: %s\n", file_name
);
94 const char *file_name
, uint8_t *trans_font
, size_t trans_len
) {
95 CFDataRef data
= CFDataCreate(0, trans_font
, trans_len
);
98 "OK: font renderer couldn't open the transcoded font: %s\n",
103 CGDataProviderRef dataProvider
= CGDataProviderCreateWithCFData(data
);
104 CGFontRef cgFontRef
= CGFontCreateWithDataProvider(dataProvider
);
105 CGDataProviderRelease(dataProvider
);
109 "OK: font renderer couldn't open the transcoded font: %s\n",
114 size_t numGlyphs
= CGFontGetNumberOfGlyphs(cgFontRef
);
115 CGFontRelease(cgFontRef
);
118 "OK: font renderer couldn't open the transcoded font: %s\n",
122 std::fprintf(stderr
, "OK: font renderer didn't crash: %s\n", file_name
);
123 // TODO(yusukes): would be better to perform LoadChar() like Linux.
129 // TODO(yusukes): Support Windows.
134 int main(int argc
, char **argv
) {
136 std::fprintf(stderr
, "Usage: %s ttf_or_otf_filename\n", argv
[0]);
140 // load the font to memory.
141 const int fd
= ::open(argv
[1], O_RDONLY
);
149 const off_t orig_len
= st
.st_size
;
151 uint8_t *orig_font
= new uint8_t[orig_len
];
152 if (::read(fd
, orig_font
, orig_len
) != orig_len
) {
153 std::fprintf(stderr
, "Failed to read file!\n");
158 // transcode the malicious font.
159 static const size_t kBigPadLen
= 1024 * 1024; // 1MB
160 uint8_t *trans_font
= new uint8_t[orig_len
+ kBigPadLen
];
161 ots::MemoryStream
output(trans_font
, orig_len
+ kBigPadLen
);
162 ots::OTSContext context
;
164 bool result
= context
.Process(&output
, orig_font
, orig_len
);
166 std::fprintf(stderr
, "OK: the malicious font was filtered: %s\n", argv
[1]);
169 const size_t trans_len
= output
.Tell();
171 return OpenAndLoadChars(argv
[1], trans_font
, trans_len
);