57 {
59 constexpr size_t kFullLengthSize = 4;
60 constexpr size_t kOffsetSize = 4;
62
63
66 return nullptr;
67 }
70 uint8_t digit = 0;
71 if (guidAscii[
i] >=
'0' && guidAscii[
i] <=
'9') {
72 digit = guidAscii[
i] -
'0';
73 }
else if (guidAscii[
i] >=
'A' && guidAscii[
i] <=
'F') {
74 digit = guidAscii[
i] -
'A' + 10;
75 } else {
77 return nullptr;
78 }
80 guidAsDigest.
data[
i / 2] = 16 * digit;
81 } else {
82 guidAsDigest.
data[
i / 2] += digit;
83 }
84 }
85
86
87 uint32_t fullLength = 0;
88 using Part = std::tuple<uint32_t, sk_sp<SkData>>;
89 std::vector<Part>
parts;
90 for (
const auto&
params : decoderApp1Params) {
91
93 continue;
94 }
96 continue;
97 }
98
99
100 const uint8_t* partGuidAscii =
params->bytes() + kSigSize;
103 continue;
104 }
105
106
107 uint32_t partFullLength = 0;
108 uint32_t partOffset = 0;
110 const uint8_t* partOffsetBytes =
112 for (
size_t i = 0;
i < 4; ++
i) {
113 partFullLength *= 256;
114 partOffset *= 256;
115 partFullLength += partFullLengthBytes[
i];
116 partOffset += partOffsetBytes[
i];
117 }
118
119
121 fullLength = partFullLength;
122 }
123
124
125 if (partFullLength != fullLength) {
126 SkCodecPrintf(
"Multiple parts had different total lengths.\n");
127 return nullptr;
128 }
129
130
133 parts.push_back({partOffset, partData});
134 }
135 if (
parts.empty() || fullLength == 0) {
136 return nullptr;
137 }
138
139
141 return std::get<0>(a) < std::get<0>(b);
142 });
143
144
146 uint8_t* xmpExtendedBase = reinterpret_cast<uint8_t*>(xmpExtendedData->writable_data());
147 uint8_t* xmpExtendedCurrent = xmpExtendedBase;
149 for (
const auto& part :
parts) {
150 uint32_t currentOffset = static_cast<uint32_t>(xmpExtendedCurrent - xmpExtendedBase);
153
154 if (partOffset != currentOffset) {
156 return nullptr;
157 }
158 if (partData->
size() > fullLength - currentOffset) {
160 return nullptr;
161 }
162 memcpy(xmpExtendedCurrent, partData->
data(), partData->
size());
163 xmpExtendedCurrent += partData->
size();
164 }
165
166 if (static_cast<uint32_t>(xmpExtendedCurrent - xmpExtendedBase) != fullLength) {
168 return nullptr;
169 }
170
171
172 md5.write(xmpExtendedData->data(), xmpExtendedData->size());
173 if (
md5.finish() != guidAsDigest) {
175 return nullptr;
176 }
177
178 return xmpExtendedData;
179}
static SkMD5::Digest md5(const SkBitmap &bm)
#define SkCodecPrintf(...)
static constexpr size_t kHeaderSize
static constexpr uint8_t kXMPExtendedSig[]
constexpr size_t kGuidAsciiSize
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
static sk_sp< SkData > MakeUninitialized(size_t length)
const void * data() const
const EmbeddedViewParams * params
const myers::Point & get< 1 >(const myers::Segment &s)
const myers::Point & get< 0 >(const myers::Segment &s)