1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "blocks_patch.h"
17 #include <cstdio>
18 #include <iostream>
19 #include <vector>
20 #include "diffpatch.h"
21
22 using namespace Hpackage;
23 using namespace std;
24
25 namespace UpdatePatch {
26 #define PATCH_MIN std::char_traits<char>::length(BSDIFF_MAGIC) + sizeof(int64_t) * 3
27 #define GET_BYTE_FROM_BUFFER(v, index, buffer) ((v) * 256 + (buffer)[index])
28 constexpr uint8_t BUFFER_MASK = 0x80;
29
ReadLE64(const uint8_t * buffer)30 static int64_t ReadLE64(const uint8_t *buffer)
31 {
32 if (buffer == nullptr) {
33 return 0;
34 }
35 int64_t y = 0;
36 int32_t index = static_cast<int32_t>(sizeof(int64_t)) - 1;
37 y = buffer[index] & static_cast<uint8_t>(~BUFFER_MASK);
38 index--;
39 y = GET_BYTE_FROM_BUFFER(y, index, buffer);
40 index--;
41 y = GET_BYTE_FROM_BUFFER(y, index, buffer);
42 index--;
43 y = GET_BYTE_FROM_BUFFER(y, index, buffer);
44 index--;
45 y = GET_BYTE_FROM_BUFFER(y, index, buffer);
46 index--;
47 y = GET_BYTE_FROM_BUFFER(y, index, buffer);
48 index--;
49 y = GET_BYTE_FROM_BUFFER(y, index, buffer);
50 index--;
51 y = GET_BYTE_FROM_BUFFER(y, index, buffer);
52
53 index = static_cast<int32_t>(sizeof(int64_t));
54 if (buffer[index - 1] & BUFFER_MASK) {
55 y = -y;
56 }
57 return y;
58 }
59
ApplyPatch()60 int32_t BlocksPatch::ApplyPatch()
61 {
62 int64_t controlDataSize = 0;
63 int64_t diffDataSize = 0;
64 int32_t ret = ReadHeader(controlDataSize, diffDataSize, newSize_);
65 if (ret != 0) {
66 PATCH_LOGE("Failed to read header ");
67 return -1;
68 }
69
70 while (newOffset_ < newSize_) {
71 ControlData ctrlData {};
72 ret = ReadControlData(ctrlData);
73 if (ret != 0) {
74 PATCH_LOGE("Failed to read control data");
75 return ret;
76 }
77 if (newOffset_ + ctrlData.diffLength > newSize_) {
78 PATCH_LOGE("Failed to check new offset %ld %zu", ctrlData.diffLength, newOffset_);
79 return PATCH_INVALID_PATCH;
80 }
81
82 ret = RestoreDiffData(ctrlData);
83 if (ret != 0) {
84 PATCH_LOGE("Failed to read diff data");
85 return ret;
86 }
87 oldOffset_ += ctrlData.diffLength;
88 newOffset_ += ctrlData.diffLength;
89 if (newOffset_ + ctrlData.extraLength > newSize_) {
90 PATCH_LOGE("Failed to check new offset %ld %zu", ctrlData.diffLength, newOffset_);
91 return PATCH_INVALID_PATCH;
92 }
93
94 ret = RestoreExtraData(ctrlData);
95 if (ret != 0) {
96 PATCH_LOGE("Failed to read extra data");
97 return ret;
98 }
99
100 newOffset_ += ctrlData.extraLength;
101 oldOffset_ += ctrlData.offsetIncrement;
102 }
103 controlDataReader_->Close();
104 diffDataReader_->Close();
105 extraDataReader_->Close();
106 return 0;
107 }
108
ReadHeader(int64_t & controlDataSize,int64_t & diffDataSize,int64_t & newSize)109 int32_t BlocksPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize)
110 {
111 if (patchInfo_.buffer == nullptr || patchInfo_.length < patchInfo_.start ||
112 patchInfo_.length - patchInfo_.start <= PATCH_MIN) {
113 PATCH_LOGE("Invalid parm. length:%zu, start:%zu", patchInfo_.length, patchInfo_.start);
114 return -1;
115 }
116 BlockBuffer patchData = {patchInfo_.buffer + patchInfo_.start, patchInfo_.length - patchInfo_.start};
117 PATCH_DEBUG("Restore patch hash %zu %zu %s",
118 patchInfo_.length, patchInfo_.start, GeneraterBufferHash(patchData).c_str());
119 uint8_t *header = patchInfo_.buffer + patchInfo_.start;
120 if (memcmp(header, BSDIFF_MAGIC, std::char_traits<char>::length(BSDIFF_MAGIC)) != 0) {
121 PATCH_LOGE("Corrupt patch, patch head != BSDIFF40");
122 return -1;
123 }
124 /* Read lengths from header */
125 size_t offset = std::char_traits<char>::length(BSDIFF_MAGIC);
126 controlDataSize = ReadLE64(header + offset);
127 offset += sizeof(int64_t);
128 diffDataSize = ReadLE64(header + offset);
129 offset += sizeof(int64_t);
130 newSize = ReadLE64(header + offset);
131 offset += sizeof(int64_t);
132 if (controlDataSize < 0) {
133 PATCH_LOGE("Invalid control data size");
134 return -1;
135 }
136 if (newSize < 0) {
137 PATCH_LOGE("Invalid new data size");
138 return -1;
139 }
140 if (diffDataSize < 0 || (diffDataSize + controlDataSize) > static_cast<int64_t>(patchInfo_.length)) {
141 PATCH_LOGE("Invalid patch data size");
142 return -1;
143 }
144 BlockBuffer patchBuffer = {header, patchInfo_.length - patchInfo_.start};
145 controlDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast<size_t>(controlDataSize), patchBuffer));
146 offset += static_cast<size_t>(controlDataSize);
147 diffDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast<size_t>(diffDataSize), patchBuffer));
148 offset += static_cast<size_t>(diffDataSize);
149 extraDataReader_.reset(new BZip2BufferReadAdapter(offset,
150 patchInfo_.length - patchInfo_.start - offset, patchBuffer));
151 if (controlDataReader_ == nullptr || diffDataReader_ == nullptr || extraDataReader_ == nullptr) {
152 PATCH_LOGE("Failed to create reader");
153 return -1;
154 }
155 controlDataReader_->Open();
156 diffDataReader_->Open();
157 extraDataReader_->Open();
158 return 0;
159 }
160
ReadControlData(ControlData & ctrlData)161 int32_t BlocksPatch::ReadControlData(ControlData &ctrlData)
162 {
163 std::vector<uint8_t> data(sizeof(int64_t), 0);
164 BlockBuffer info = {data.data(), sizeof(int64_t)};
165 int32_t ret = controlDataReader_->ReadData(info);
166 if (ret != 0) {
167 PATCH_LOGE("Failed to read diffLength");
168 return ret;
169 }
170 ctrlData.diffLength = ReadLE64(info.buffer);
171 ret = controlDataReader_->ReadData(info);
172 if (ret != 0) {
173 PATCH_LOGE("Failed to read extraLength");
174 return ret;
175 }
176 ctrlData.extraLength = ReadLE64(info.buffer);
177 ret = controlDataReader_->ReadData(info);
178 if (ret != 0) {
179 PATCH_LOGE("Failed to read offsetIncrement");
180 return ret;
181 }
182 ctrlData.offsetIncrement = ReadLE64(info.buffer);
183 return 0;
184 }
185
ReadHeader(int64_t & controlDataSize,int64_t & diffDataSize,int64_t & newSize)186 int32_t BlocksBufferPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize)
187 {
188 int32_t ret = BlocksPatch::ReadHeader(controlDataSize, diffDataSize, newSize);
189 if (ret != 0) {
190 PATCH_LOGE("Failed to read header");
191 return -1;
192 }
193 PATCH_LOGI("ReadHeader controlDataSize: %ld %ld %ld", controlDataSize, diffDataSize, newSize);
194 newData_.resize(newSize);
195 return 0;
196 }
197
RestoreDiffData(const ControlData & ctrlData)198 int32_t BlocksBufferPatch::RestoreDiffData(const ControlData &ctrlData)
199 {
200 if (ctrlData.diffLength <= 0) {
201 return 0;
202 }
203 BlockBuffer diffData = {newData_.data() + newOffset_, static_cast<size_t>(ctrlData.diffLength)};
204 int32_t ret = diffDataReader_->ReadData(diffData);
205 if (ret != 0) {
206 PATCH_LOGE("Failed to read diff data");
207 return ret;
208 }
209
210 for (int64_t i = 0; i < ctrlData.diffLength; i++) {
211 if (((oldOffset_ + i) >= 0) && (static_cast<size_t>(oldOffset_ + i) < oldInfo_.length)) {
212 newData_[newOffset_ + i] += oldInfo_.buffer[oldOffset_ + i];
213 }
214 }
215 return 0;
216 }
217
RestoreExtraData(const ControlData & ctrlData)218 int32_t BlocksBufferPatch::RestoreExtraData(const ControlData &ctrlData)
219 {
220 if (ctrlData.extraLength <= 0) {
221 return 0;
222 }
223 BlockBuffer extraData = {newData_.data() + newOffset_, static_cast<size_t>(ctrlData.extraLength)};
224 int32_t ret = extraDataReader_->ReadData(extraData);
225 if (ret != 0) {
226 PATCH_LOGE("Failed to read extra data");
227 return ret;
228 }
229 return 0;
230 }
231
RestoreDiffData(const ControlData & ctrlData)232 int32_t BlocksStreamPatch::RestoreDiffData(const ControlData &ctrlData)
233 {
234 if (ctrlData.diffLength <= 0) {
235 return 0;
236 }
237 std::vector<uint8_t> diffData(ctrlData.diffLength);
238 BlockBuffer diffBuffer = {diffData.data(), diffData.size()};
239 int32_t ret = diffDataReader_->ReadData(diffBuffer);
240 if (ret != 0) {
241 PATCH_LOGE("Failed to read diff data");
242 return ret;
243 }
244
245 size_t oldOffset = static_cast<size_t>(oldOffset_);
246 size_t oldLength = stream_->GetFileLength();
247 PkgBuffer buffer {};
248 if (stream_->GetStreamType() == PkgStream::PkgStreamType_MemoryMap ||
249 stream_->GetStreamType() == PkgStream::PkgStreamType_Buffer) {
250 ret = stream_->GetBuffer(buffer);
251 if (ret != 0) {
252 PATCH_LOGE("Failed to get old buffer");
253 return ret;
254 }
255 } else {
256 std::vector<uint8_t> oldData(ctrlData.diffLength);
257 size_t readLen = 0;
258 ret = stream_->Read(buffer, oldOffset_, ctrlData.diffLength, readLen);
259 if (ret != 0 || readLen != static_cast<size_t>(ctrlData.diffLength)) {
260 PATCH_LOGE("Failed to get old buffer");
261 return ret;
262 }
263 oldOffset = 0;
264 }
265 for (int64_t i = 0; i < ctrlData.diffLength; i++) {
266 if ((oldOffset_ + i >= 0) && (static_cast<size_t>(oldOffset_ + i) < oldLength)) {
267 diffData[i] += buffer.buffer[static_cast<int64_t>(oldOffset) + i];
268 }
269 }
270 // write
271 return writer_->Write(newOffset_, diffBuffer, static_cast<size_t>(ctrlData.diffLength));
272 }
273
RestoreExtraData(const ControlData & ctrlData)274 int32_t BlocksStreamPatch::RestoreExtraData(const ControlData &ctrlData)
275 {
276 if (ctrlData.extraLength <= 0) {
277 return 0;
278 }
279 std::vector<uint8_t> extraData(ctrlData.extraLength);
280 BlockBuffer extraBuffer = {extraData.data(), static_cast<size_t>(ctrlData.extraLength)};
281 int32_t ret = extraDataReader_->ReadData(extraBuffer);
282 if (ret != 0) {
283 PATCH_LOGE("Failed to read extra data");
284 return ret;
285 }
286 // write
287 return writer_->Write(newOffset_, extraBuffer, static_cast<size_t>(ctrlData.extraLength));
288 }
289 } // namespace UpdatePatch
290