Android: Fix potential null-ptr deref
[chromium-blink-merge.git] / content / common / font_config_ipc_linux.cc
blob540d7d88825c61d660eda9c2591b2adeb6b51054
1 // Copyright (c) 2012 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.
5 #include "content/common/font_config_ipc_linux.h"
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/mman.h>
10 #include <sys/socket.h>
11 #include <sys/stat.h>
12 #include <sys/uio.h>
13 #include <unistd.h>
15 #include "base/files/file_util.h"
16 #include "base/files/memory_mapped_file.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/pickle.h"
19 #include "base/posix/unix_domain_socket_linux.h"
20 #include "base/threading/thread_restrictions.h"
21 #include "base/trace_event/trace_event.h"
22 #include "skia/ext/refptr.h"
23 #include "skia/ext/skia_utils_base.h"
24 #include "third_party/skia/include/core/SkData.h"
25 #include "third_party/skia/include/core/SkStream.h"
26 #include "third_party/skia/include/core/SkTypeface.h"
28 namespace content {
30 class FontConfigIPC::MappedFontFile
31 : public base::RefCountedThreadSafe<MappedFontFile> {
32 public:
33 explicit MappedFontFile(uint32_t font_id) : font_id_(font_id) {}
35 uint32_t font_id() const { return font_id_; }
37 bool Initialize(int fd) {
38 base::ThreadRestrictions::ScopedAllowIO allow_mmap;
39 return mapped_font_file_.Initialize(base::File(fd));
42 SkMemoryStream* CreateMemoryStream() {
43 DCHECK(mapped_font_file_.IsValid());
44 auto data = skia::AdoptRef(SkData::NewWithProc(
45 mapped_font_file_.data(), mapped_font_file_.length(),
46 &MappedFontFile::ReleaseProc, this));
47 if (!data)
48 return nullptr;
49 AddRef();
50 return new SkMemoryStream(data.get());
53 private:
54 friend class base::RefCountedThreadSafe<MappedFontFile>;
56 ~MappedFontFile() {
57 auto font_config = static_cast<FontConfigIPC*>(FontConfigIPC::RefGlobal());
58 font_config->RemoveMappedFontFile(this);
61 static void ReleaseProc(const void* ptr, size_t length, void* context) {
62 base::ThreadRestrictions::ScopedAllowIO allow_munmap;
63 static_cast<MappedFontFile*>(context)->Release();
66 uint32_t font_id_;
67 base::MemoryMappedFile mapped_font_file_;
70 void CloseFD(int fd) {
71 int err = IGNORE_EINTR(close(fd));
72 DCHECK(!err);
75 FontConfigIPC::FontConfigIPC(int fd)
76 : fd_(fd) {
79 FontConfigIPC::~FontConfigIPC() {
80 CloseFD(fd_);
83 bool FontConfigIPC::matchFamilyName(const char familyName[],
84 SkTypeface::Style requestedStyle,
85 FontIdentity* outFontIdentity,
86 SkString* outFamilyName,
87 SkTypeface::Style* outStyle) {
88 TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::matchFamilyName");
89 size_t familyNameLen = familyName ? strlen(familyName) : 0;
90 if (familyNameLen > kMaxFontFamilyLength)
91 return false;
93 Pickle request;
94 request.WriteInt(METHOD_MATCH);
95 request.WriteData(familyName, familyNameLen);
96 request.WriteUInt32(requestedStyle);
98 uint8_t reply_buf[2048];
99 const ssize_t r = UnixDomainSocket::SendRecvMsg(fd_, reply_buf,
100 sizeof(reply_buf), NULL,
101 request);
102 if (r == -1)
103 return false;
105 Pickle reply(reinterpret_cast<char*>(reply_buf), r);
106 PickleIterator iter(reply);
107 bool result;
108 if (!iter.ReadBool(&result))
109 return false;
110 if (!result)
111 return false;
113 SkString reply_family;
114 FontIdentity reply_identity;
115 uint32_t reply_style;
116 if (!skia::ReadSkString(&iter, &reply_family) ||
117 !skia::ReadSkFontIdentity(&iter, &reply_identity) ||
118 !iter.ReadUInt32(&reply_style)) {
119 return false;
122 if (outFontIdentity)
123 *outFontIdentity = reply_identity;
124 if (outFamilyName)
125 *outFamilyName = reply_family;
126 if (outStyle)
127 *outStyle = static_cast<SkTypeface::Style>(reply_style);
129 return true;
132 SkStreamAsset* FontConfigIPC::openStream(const FontIdentity& identity) {
133 TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::openStream");
136 base::AutoLock lock(lock_);
137 auto mapped_font_files_it = mapped_font_files_.find(identity.fID);
138 if (mapped_font_files_it != mapped_font_files_.end())
139 return mapped_font_files_it->second->CreateMemoryStream();
142 Pickle request;
143 request.WriteInt(METHOD_OPEN);
144 request.WriteUInt32(identity.fID);
146 int result_fd = -1;
147 uint8_t reply_buf[256];
148 const ssize_t r = UnixDomainSocket::SendRecvMsg(fd_, reply_buf,
149 sizeof(reply_buf),
150 &result_fd, request);
152 if (r == -1)
153 return NULL;
155 Pickle reply(reinterpret_cast<char*>(reply_buf), r);
156 bool result;
157 PickleIterator iter(reply);
158 if (!iter.ReadBool(&result) || !result) {
159 if (result_fd)
160 CloseFD(result_fd);
161 return NULL;
164 scoped_refptr<MappedFontFile> mapped_font_file =
165 new MappedFontFile(identity.fID);
166 if (!mapped_font_file->Initialize(result_fd))
167 return nullptr;
170 base::AutoLock lock(lock_);
171 auto mapped_font_files_it =
172 mapped_font_files_.insert(std::make_pair(mapped_font_file->font_id(),
173 mapped_font_file.get())).first;
174 return mapped_font_files_it->second->CreateMemoryStream();
178 void FontConfigIPC::RemoveMappedFontFile(MappedFontFile* mapped_font_file) {
179 base::AutoLock lock(lock_);
180 mapped_font_files_.erase(mapped_font_file->font_id());
183 } // namespace content