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