blob: 66c2b759b448fd95e10b29e33e7b6b70b0bf4bb6 [file] [log] [blame]
yusukes@chromium.orgd257d182009-11-04 04:56:32 +00001// 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.
4
5#include <fcntl.h>
6#include <ft2build.h>
7#include FT_FREETYPE_H
8#include <sys/stat.h>
9#include <sys/types.h>
10
11#include <cstdio>
12#include <cstdlib>
13#include <cstring>
14
15#include "opentype-sanitiser.h"
16#include "ots-memory-stream.h"
17
18namespace {
19
20void LoadChar(FT_Face face, int pt, FT_ULong c) {
21 FT_Matrix matrix;
22 matrix.xx = matrix.yy = 1 << 16;
23 matrix.xy = matrix.yx = 0 << 16;
24
25 FT_Set_Char_Size(face, pt * (1 << 6), 0, 72, 0);
26 FT_Set_Transform(face, &matrix, 0);
27 FT_Load_Char(face, c, FT_LOAD_RENDER);
28}
29
30int OpenAndLoadChars(FT_Library library, const char *file_name,
31 uint8_t *trans_font, size_t trans_len) {
32 FT_Face trans_face;
33 FT_Error error
34 = FT_New_Memory_Face(library, trans_font, trans_len, 0, &trans_face);
35 if (error) {
36 std::fprintf(stderr,
37 "OK: FreeType2 couldn't open the transcoded font: %s\n",
38 file_name);
39 return 0;
40 }
41
42 static const int kPts[] = {100, 20, 18, 16, 12, 10, 8}; // pt
43 static const size_t kPtsLen = sizeof(kPts) / sizeof(kPts[0]);
44
45 static const int kUnicodeRanges[] = {
46 0x0020, 0x007E, // Basic Latin (ASCII)
47 0x00A1, 0x017F, // Latin-1
48 0x1100, 0x11FF, // Hangul
49 0x3040, 0x309F, // Japanese HIRAGANA letters
50 0x3130, 0x318F, // Hangul
51 0x4E00, 0x4F00, // CJK Kanji/Hanja
52 0xAC00, 0xAD00, // Hangul
53 };
54 static const size_t kUnicodeRangesLen
55 = sizeof(kUnicodeRanges) / sizeof(kUnicodeRanges[0]);
56
57 for (size_t i = 0; i < kPtsLen; ++i) {
58 for (size_t j = 0; j < kUnicodeRangesLen; j += 2) {
59 for (int k = 0; k <= kUnicodeRanges[j + 1] - kUnicodeRanges[j]; ++k) {
60 LoadChar(trans_face, kPts[i], kUnicodeRanges[j] + k);
61 }
62 }
63 }
64
65 std::fprintf(stderr, "OK: FreeType2 didn't crash: %s\n", file_name);
66 return 0;
67}
68
69} // namespace
70
71int main(int argc, char **argv) {
72 ots::DisableDebugOutput(); // turn off ERROR and WARNING outputs.
73
74 if (argc != 2) {
75 std::fprintf(stderr, "Usage: %s ttf_or_otf_filename\n", argv[0]);
76 return 1;
77 }
78
79 // load the font to memory.
80 const int fd = ::open(argv[1], O_RDONLY);
81 if (fd < 0) {
82 ::perror("open");
83 return 1;
84 }
85
86 struct stat st;
87 ::fstat(fd, &st);
88 const off_t orig_len = st.st_size;
89
90 uint8_t *orig_font = new uint8_t[orig_len];
91 if (::read(fd, orig_font, orig_len) != orig_len) {
92 std::fprintf(stderr, "Failed to read file!\n");
93 return 1;
94 }
95 ::close(fd);
96
97 // transcode the malicious font.
98 static const size_t kBigPadLen = 1024 * 1024; // 1MB
99 uint8_t *trans_font = new uint8_t[orig_len + kBigPadLen];
100 ots::MemoryStream output(trans_font, orig_len + kBigPadLen);
101
102 bool result = ots::Process(&output, orig_font, orig_len);
103 if (!result) {
104 std::fprintf(stderr, "OK: the malicious font was filtered: %s\n", argv[1]);
105 return 0;
106 }
107 const size_t trans_len = output.Tell();
108
109 FT_Library library;
110 FT_Error error = FT_Init_FreeType(&library);
111 if (error) {
112 std::fprintf(stderr, "Failed to initialize FreeType2!\n");
113 return 1;
114 }
115
116 return OpenAndLoadChars(library, argv[1], trans_font, trans_len);
117}