1 /*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/core/SkDescriptor.h"
9 #include <string.h>
10
11 #include <new>
12
13 #include "include/core/SkTypes.h"
14 #include "include/private/SkTo.h"
15 #include "include/private/chromium/SkChromeRemoteGlyphCache.h"
16 #include "src/core/SkOpts.h"
17 #include "src/core/SkReadBuffer.h"
18 #include "src/core/SkWriteBuffer.h"
19 #include "src/gpu/GrResourceProvider.h"
20
Alloc(size_t length)21 std::unique_ptr<SkDescriptor> SkDescriptor::Alloc(size_t length) {
22 SkASSERT(length >= sizeof(SkDescriptor) && SkAlign4(length) == length);
23 void* allocation = ::operator new(length);
24 return std::unique_ptr<SkDescriptor>(new (allocation) SkDescriptor{});
25 }
26
operator delete(void * p)27 void SkDescriptor::operator delete(void* p) { ::operator delete(p); }
operator new(size_t)28 void* SkDescriptor::operator new(size_t) {
29 SK_ABORT("Descriptors are created with placement new.");
30 }
31
flatten(SkWriteBuffer & buffer) const32 void SkDescriptor::flatten(SkWriteBuffer& buffer) const {
33 buffer.writePad32(static_cast<const void*>(this), this->fLength);
34 }
35
addEntry(uint32_t tag,size_t length,const void * data)36 void* SkDescriptor::addEntry(uint32_t tag, size_t length, const void* data) {
37 SkASSERT(tag);
38 SkASSERT(SkAlign4(length) == length);
39 SkASSERT(this->findEntry(tag, nullptr) == nullptr);
40
41 Entry* entry = (Entry*)((char*)this + fLength);
42 entry->fTag = tag;
43 entry->fLen = SkToU32(length);
44 if (data) {
45 memcpy(entry + 1, data, length);
46 }
47
48 fCount += 1;
49 fLength = SkToU32(fLength + sizeof(Entry) + length);
50 return (entry + 1); // return its data
51 }
52
computeChecksum()53 void SkDescriptor::computeChecksum() {
54 fChecksum = SkDescriptor::ComputeChecksum(this);
55 }
56
findEntry(uint32_t tag,uint32_t * length) const57 const void* SkDescriptor::findEntry(uint32_t tag, uint32_t* length) const {
58 const Entry* entry = (const Entry*)(this + 1);
59 int count = fCount;
60
61 while (--count >= 0) {
62 if (entry->fTag == tag) {
63 if (length) {
64 *length = entry->fLen;
65 }
66 return entry + 1;
67 }
68 entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
69 }
70 return nullptr;
71 }
72
copy() const73 std::unique_ptr<SkDescriptor> SkDescriptor::copy() const {
74 std::unique_ptr<SkDescriptor> desc = SkDescriptor::Alloc(fLength);
75 memcpy(desc.get(), this, fLength);
76 return desc;
77 }
78
operator ==(const SkDescriptor & other) const79 bool SkDescriptor::operator==(const SkDescriptor& other) const {
80 // the first value we should look at is the checksum, so this loop
81 // should terminate early if they descriptors are different.
82 // NOTE: if we wrote a sentinel value at the end of each, we could
83 // remove the aa < stop test in the loop...
84 const uint32_t* aa = (const uint32_t*)this;
85 const uint32_t* bb = (const uint32_t*)&other;
86 const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
87 do {
88 if (*aa++ != *bb++)
89 return false;
90 } while (aa < stop);
91 return true;
92 }
93
dumpRec() const94 SkString SkDescriptor::dumpRec() const {
95 const SkScalerContextRec* rec = static_cast<const SkScalerContextRec*>(
96 this->findEntry(kRec_SkDescriptorTag, nullptr));
97
98 SkString result;
99 result.appendf(" Checksum: %x\n", fChecksum);
100 if (rec != nullptr) {
101 result.append(rec->dump());
102 }
103 return result;
104 }
105
ComputeChecksum(const SkDescriptor * desc)106 uint32_t SkDescriptor::ComputeChecksum(const SkDescriptor* desc) {
107 const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field
108 size_t len = desc->fLength - sizeof(uint32_t);
109 return SkOpts::hash(ptr, len);
110 }
111
isValid() const112 bool SkDescriptor::isValid() const {
113 uint32_t count = fCount;
114 size_t lengthRemaining = this->fLength;
115 if (lengthRemaining < sizeof(SkDescriptor)) {
116 return false;
117 }
118 lengthRemaining -= sizeof(SkDescriptor);
119 size_t offset = sizeof(SkDescriptor);
120
121 while (lengthRemaining > 0 && count > 0) {
122 if (lengthRemaining < sizeof(Entry)) {
123 return false;
124 }
125 lengthRemaining -= sizeof(Entry);
126
127 const Entry* entry = (const Entry*)(reinterpret_cast<const char*>(this) + offset);
128
129 if (lengthRemaining < entry->fLen) {
130 return false;
131 }
132 lengthRemaining -= entry->fLen;
133
134 // rec tags are always a known size.
135 if (entry->fTag == kRec_SkDescriptorTag && entry->fLen != sizeof(SkScalerContextRec)) {
136 return false;
137 }
138
139 offset += sizeof(Entry) + entry->fLen;
140 count--;
141 }
142 return lengthRemaining == 0 && count == 0;
143 }
144
145 SkAutoDescriptor::SkAutoDescriptor() = default;
SkAutoDescriptor(size_t size)146 SkAutoDescriptor::SkAutoDescriptor(size_t size) { this->reset(size); }
SkAutoDescriptor(const SkDescriptor & desc)147 SkAutoDescriptor::SkAutoDescriptor(const SkDescriptor& desc) { this->reset(desc); }
SkAutoDescriptor(const SkAutoDescriptor & that)148 SkAutoDescriptor::SkAutoDescriptor(const SkAutoDescriptor& that) {
149 this->reset(*that.getDesc());
150 }
operator =(const SkAutoDescriptor & that)151 SkAutoDescriptor& SkAutoDescriptor::operator=(const SkAutoDescriptor& that) {
152 this->reset(*that.getDesc());
153 return *this;
154 }
SkAutoDescriptor(SkAutoDescriptor && that)155 SkAutoDescriptor::SkAutoDescriptor(SkAutoDescriptor&& that) {
156 if (that.fDesc == (SkDescriptor*)&that.fStorage) {
157 this->reset(*that.getDesc());
158 } else {
159 fDesc = that.fDesc;
160 that.fDesc = nullptr;
161 }
162 }
operator =(SkAutoDescriptor && that)163 SkAutoDescriptor& SkAutoDescriptor::operator=(SkAutoDescriptor&& that) {
164 if (that.fDesc == (SkDescriptor*)&that.fStorage) {
165 this->reset(*that.getDesc());
166 } else {
167 this->free();
168 fDesc = that.fDesc;
169 that.fDesc = nullptr;
170 }
171 return *this;
172 }
173
~SkAutoDescriptor()174 SkAutoDescriptor::~SkAutoDescriptor() { this->free(); }
175
MakeFromBuffer(SkReadBuffer & buffer)176 std::optional<SkAutoDescriptor> SkAutoDescriptor::MakeFromBuffer(SkReadBuffer& buffer) {
177 SkDescriptor descriptorHeader;
178 if (!buffer.readPad32(&descriptorHeader, sizeof(SkDescriptor))) { return {}; }
179
180 // Basic bounds check on header length to make sure that bodyLength calculation does not
181 // underflow.
182 if (descriptorHeader.getLength() < sizeof(SkDescriptor)) { return {}; }
183 uint32_t bodyLength = descriptorHeader.getLength() - sizeof(SkDescriptor);
184
185 // Make sure the fLength makes sense with respect to the incoming data.
186 if (bodyLength > buffer.available()) {
187 return {};
188 }
189
190 SkAutoDescriptor ad{descriptorHeader.getLength()};
191 memcpy(ad.fDesc, &descriptorHeader, sizeof(SkDescriptor));
192 if (!buffer.readPad32(SkTAddOffset<void>(ad.fDesc, sizeof(SkDescriptor)), bodyLength)) {
193 return {};
194 }
195
196 if (SkDescriptor::ComputeChecksum(ad.getDesc()) != ad.getDesc()->fChecksum) { return {}; }
197 if (!ad.getDesc()->isValid()) { return {}; }
198
199 return {ad};
200 }
201
reset(size_t size)202 void SkAutoDescriptor::reset(size_t size) {
203 this->free();
204 if (size <= sizeof(fStorage)) {
205 fDesc = new (&fStorage) SkDescriptor{};
206 } else {
207 fDesc = SkDescriptor::Alloc(size).release();
208 }
209 }
210
reset(const SkDescriptor & desc)211 void SkAutoDescriptor::reset(const SkDescriptor& desc) {
212 size_t size = desc.getLength();
213 this->reset(size);
214 memcpy(fDesc, &desc, size);
215 }
216
free()217 void SkAutoDescriptor::free() {
218 if (fDesc == (SkDescriptor*)&fStorage) {
219 fDesc->~SkDescriptor();
220 } else {
221 delete fDesc;
222 }
223 }
224
225
226