• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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