1/*
2 * Copyright (c) 2024-2024 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#include "byte_buffer.h"
16#include <cstdio>
17#include <algorithm>
18#include "securec.h"
19#include "signature_tools_log.h"
20
21namespace OHOS {
22namespace SignatureTools {
23
24const int32_t ByteBuffer::MAX_PRINT_LENGTH = 200;
25const int32_t ByteBuffer::HEX_PRINT_LENGTH = 3;
26
27template<typename T>
28std::shared_ptr<T> make_shared_array(size_t size)
29{
30    if (size <= 0) {
31        return NULL;
32    }
33    T* buffer = new (std::nothrow)T[size];
34    if (!buffer) {
35        SIGNATURE_TOOLS_LOGE("new size failed");
36        return NULL;
37    }
38    return std::shared_ptr<T>(buffer, [] (T* p) { delete[] p; });
39}
40
41ByteBuffer::ByteBuffer() : buffer(nullptr), position(0), limit(0), capacity(0)
42{
43}
44
45ByteBuffer::ByteBuffer(int32_t bufferCapacity) : buffer(nullptr), position(0), limit(0), capacity(0)
46{
47    Init(bufferCapacity);
48}
49
50ByteBuffer::ByteBuffer(const char* arr, int32_t length) : buffer(nullptr), position(0), limit(0), capacity(0)
51{
52    Init(length);
53    PutData(0, arr, length);
54}
55
56ByteBuffer::ByteBuffer(const ByteBuffer& other) : buffer(nullptr), position(0), limit(0), capacity(0)
57{
58    Init(other.GetCapacity());
59    if (buffer != nullptr && capacity > 0) {
60        if (memcpy_s(buffer.get(), capacity, other.GetBufferPtr(), other.GetCapacity()) != EOK) {
61            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
62            return;
63        }
64        position = other.GetPosition();
65        limit = other.GetLimit();
66    }
67}
68
69ByteBuffer::~ByteBuffer()
70{
71}
72
73void ByteBuffer::Init(int32_t bufferCapacity)
74{
75    if (bufferCapacity > 0) {
76        buffer = make_shared_array<char>(bufferCapacity);
77        if (buffer != nullptr) {
78            if (memset_s(buffer.get(), bufferCapacity, 0, bufferCapacity) != EOK) {
79                SIGNATURE_TOOLS_LOGE("memcpy_s failed");
80            }
81            limit = bufferCapacity;
82            capacity = bufferCapacity;
83        }
84    } else {
85        SIGNATURE_TOOLS_LOGE("bufferCapacity %d is too small", bufferCapacity);
86    }
87}
88
89ByteBuffer& ByteBuffer::operator=(const ByteBuffer& other)
90{
91    if (&other == this) {
92        return *this;
93    }
94    // std::unique_ptr reset(),will first release the original object and then point to the new object
95    buffer = nullptr;
96    Init(other.GetCapacity());
97    if (buffer != nullptr && other.GetBufferPtr() != nullptr && capacity > 0) {
98        if (memcpy_s(buffer.get(), capacity, other.GetBufferPtr(), other.GetCapacity()) != EOK) {
99            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
100            return *this;
101        }
102        position = other.GetPosition();
103        limit = other.GetLimit();
104    }
105    return *this;
106}
107
108bool ByteBuffer::CheckInputForGettingData(int32_t index, int32_t dataLen)
109{
110    if (buffer == nullptr) {
111        SIGNATURE_TOOLS_LOGE("buffer is nullptr");
112        return false;
113    }
114    if (index < 0) {
115        SIGNATURE_TOOLS_LOGE("invalid index %d", index);
116        return false;
117    }
118    int64_t getDataLast = static_cast<int64_t>(position) + static_cast<int64_t>(index) +
119        static_cast<int64_t>(dataLen);
120    if (getDataLast > static_cast<int64_t>(limit)) {
121        SIGNATURE_TOOLS_LOGE("position: %d, index: %d, limit: %d", position, index, limit);
122        return false;
123    }
124    return true;
125}
126
127bool ByteBuffer::GetInt64(int64_t& value)
128{
129    if (!GetInt64(0, value)) {
130        SIGNATURE_TOOLS_LOGE("GetInt64 failed");
131        return false;
132    }
133    position += sizeof(int64_t);
134    return true;
135}
136
137bool ByteBuffer::GetInt64(int32_t index, int64_t& value)
138{
139    if (!CheckInputForGettingData(index, sizeof(int64_t))) {
140        SIGNATURE_TOOLS_LOGE("Failed to get Int64");
141        return false;
142    }
143    if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(int64_t)) != EOK) {
144        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
145        return false;
146    }
147    return true;
148}
149
150int32_t ByteBuffer::GetCapacity() const
151{
152    return capacity;
153}
154
155const char* ByteBuffer::GetBufferPtr() const
156{
157    return buffer.get();
158}
159
160bool ByteBuffer::GetInt32(int32_t& value)
161{
162    if (!GetInt32(0, value)) {
163        SIGNATURE_TOOLS_LOGE("GetInt32 failed");
164        return false;
165    }
166    position += sizeof(int32_t);
167    return true;
168}
169
170bool ByteBuffer::GetInt32(int32_t index, int32_t& value)
171{
172    if (!CheckInputForGettingData(index, sizeof(int32_t))) {
173        SIGNATURE_TOOLS_LOGE("Failed to get Int32");
174        return false;
175    }
176    if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(int32_t)) != EOK) {
177        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
178        return false;
179    }
180    return true;
181}
182
183bool ByteBuffer::GetUInt32(int32_t index, uint32_t& value)
184{
185    if (!CheckInputForGettingData(index, sizeof(uint32_t))) {
186        SIGNATURE_TOOLS_LOGE("Failed to get UInt32");
187        return false;
188    }
189    if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(uint32_t)) != EOK) {
190        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
191        return false;
192    }
193    return true;
194}
195
196bool ByteBuffer::GetUInt32(uint32_t& value)
197{
198    if (!GetUInt32(0, value)) {
199        SIGNATURE_TOOLS_LOGE("GetUInt32 failed");
200        return false;
201    }
202    position += sizeof(uint32_t);
203    return true;
204}
205
206bool ByteBuffer::GetUInt16(uint16_t& value)
207{
208    if (!GetUInt16(0, value)) {
209        SIGNATURE_TOOLS_LOGE("GetUInt16 failed");
210        return false;
211    }
212    position += sizeof(uint16_t);
213    return true;
214}
215
216bool ByteBuffer::GetUInt16(int32_t index, uint16_t& value)
217{
218    if (!CheckInputForGettingData(index, sizeof(uint16_t))) {
219        SIGNATURE_TOOLS_LOGE("Failed to get UInt16");
220        return false;
221    }
222    if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(uint16_t)) != EOK) {
223        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
224        return false;
225    }
226    return true;
227}
228
229bool ByteBuffer::GetInt16(int16_t& value)
230{
231    if (!GetInt16(0, value)) {
232        SIGNATURE_TOOLS_LOGE("GetInt16 failed");
233        return false;
234    }
235    position += sizeof(int16_t);
236    return true;
237}
238
239bool ByteBuffer::GetInt16(int32_t index, int16_t& value)
240{
241    if (!CheckInputForGettingData(index, sizeof(int16_t))) {
242        SIGNATURE_TOOLS_LOGE("Failed to get Int16");
243        return false;
244    }
245    if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(int16_t)) != EOK) {
246        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
247        return false;
248    }
249    return true;
250}
251
252bool ByteBuffer::GetUInt8(uint8_t& value)
253{
254    if (!GetUInt8(0, value)) {
255        SIGNATURE_TOOLS_LOGE("GetUInt8 failed");
256        return false;
257    }
258    position += sizeof(uint8_t);
259    return true;
260}
261
262bool ByteBuffer::GetUInt8(int32_t index, uint8_t& value)
263{
264    if (!CheckInputForGettingData(index, sizeof(uint8_t))) {
265        SIGNATURE_TOOLS_LOGE("Failed to get UInt8");
266        return false;
267    }
268    if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(uint8_t)) != EOK) {
269        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
270        return false;
271    }
272    return true;
273}
274
275bool ByteBuffer::GetInt8(int8_t& value)
276{
277    if (!GetInt8(0, value)) {
278        SIGNATURE_TOOLS_LOGE("GetInt8 failed");
279        return false;
280    }
281    position += sizeof(int8_t);
282    return true;
283}
284
285bool ByteBuffer::GetInt8(int32_t index, int8_t& value)
286{
287    if (!CheckInputForGettingData(index, sizeof(int8_t))) {
288        SIGNATURE_TOOLS_LOGE("Failed to get Int8");
289        return false;
290    }
291    if (memcpy_s(&value, sizeof(value), (buffer.get() + position + index), sizeof(int8_t)) != EOK) {
292        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
293        return false;
294    }
295    return true;
296}
297
298void ByteBuffer::PutInt64(int64_t value)
299{
300    if ((limit - position) >= static_cast<int64_t>(sizeof(value))) {
301        if (memcpy_s(buffer.get() + position, limit - position, &value, sizeof(value)) != EOK) {
302            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
303        } else {
304            position += sizeof(value);
305        }
306    }
307}
308
309void ByteBuffer::PutInt32(int32_t offset, int32_t value)
310{
311    if (buffer != nullptr && offset >= 0 && limit - offset >= static_cast<int32_t>(sizeof(value))) {
312        if (memcpy_s((buffer.get() + offset), (limit - offset), &value, sizeof(value)) != EOK) {
313            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
314        }
315    }
316}
317
318void ByteBuffer::PutInt16(int32_t offset, int16_t value)
319{
320    if (buffer != nullptr && offset >= 0 && limit - offset >= static_cast<int16_t>(sizeof(value))) {
321        if (memcpy_s((buffer.get() + offset), (limit - offset), &value, sizeof(value)) != EOK) {
322            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
323        }
324    }
325}
326
327void ByteBuffer::PutByte(int32_t offset, char value)
328{
329    if (buffer != nullptr && offset >= 0 && limit - offset >= static_cast<int32_t>(sizeof(value))) {
330        if (memcpy_s((buffer.get() + offset), (limit - offset), (&value), sizeof(value)) != EOK) {
331            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
332        }
333    }
334}
335
336void ByteBuffer::PutData(int32_t offset, const char data[], int32_t len)
337{
338    if (buffer != nullptr && data != nullptr && offset >= 0 && len > 0 && (limit - offset) >= len) {
339        if (memcpy_s((buffer.get() + offset), (limit - offset), data, len) != EOK) {
340            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
341        }
342    }
343}
344
345void ByteBuffer::PutData(int32_t offset, const int8_t data[], int32_t len)
346{
347    if (buffer != nullptr && data != nullptr && offset >= 0 && len > 0 && (limit - offset) >= len) {
348        if (memcpy_s((buffer.get() + offset), (limit - offset), data, len) != EOK) {
349            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
350        }
351    }
352}
353
354void ByteBuffer::PutData(int32_t offset, const char data[], int32_t len, int32_t type)
355{
356    static int offsetAdd = 0;
357    if (buffer != nullptr && data != nullptr && offset >= 0 && len > 0 && (limit - offset) >= len) {
358        if (memcpy_s((buffer.get() + offsetAdd), (limit - offsetAdd), data, len) != EOK) {
359            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
360        }
361        offsetAdd += offset;
362    }
363}
364
365void ByteBuffer::PutInt32(int32_t value)
366{
367    if (limit - position >= static_cast<int32_t>(sizeof(value))) {
368        if (memcpy_s(buffer.get() + position, limit - position, &value, sizeof(value)) != EOK) {
369            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
370        } else {
371            position += sizeof(value);
372        }
373    }
374}
375
376void ByteBuffer::PutInt16(int16_t value)
377{
378    if (limit - position >= static_cast<int16_t>(sizeof(value))) {
379        if (memcpy_s(buffer.get() + position, limit - position, &value, sizeof(value)) != EOK) {
380            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
381        } else {
382            position += sizeof(value);
383        }
384    }
385}
386
387void ByteBuffer::PutUInt8(uint8_t value)
388{
389    if (limit - position >= static_cast<int8_t>(sizeof(value))) {
390        if (memcpy_s(buffer.get() + position, limit - position, &value, sizeof(value)) != EOK) {
391            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
392        } else {
393            position += sizeof(value);
394        }
395    }
396}
397
398void ByteBuffer::PutUInt16(uint16_t value)
399{
400    if (limit - position >= static_cast<uint16_t>(sizeof(value))) {
401        if (memcpy_s(buffer.get() + position, limit - position, &value, sizeof(value)) != EOK) {
402            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
403        } else {
404            position += sizeof(value);
405        }
406    }
407}
408
409void ByteBuffer::PutUInt32(uint32_t value)
410{
411    if (limit - position >= static_cast<uint32_t>(sizeof(value))) {
412        if (memcpy_s(buffer.get() + position, limit - position, &value, sizeof(value)) != EOK) {
413            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
414        } else {
415            position += sizeof(value);
416        }
417    }
418}
419
420void ByteBuffer::ClearData()
421{
422    if (buffer != nullptr && position < capacity) {
423        if (memset_s(buffer.get() + position, capacity - position, 0, capacity - position) != EOK) {
424            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
425        }
426    }
427}
428
429void ByteBuffer::PutByte(char value)
430{
431    if (buffer != nullptr && limit - position >= static_cast<char>(sizeof(value))) {
432        if (memcpy_s(buffer.get() + position, limit - position, &value, sizeof(value)) != EOK) {
433            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
434        } else {
435            position += sizeof(value);
436        }
437    }
438}
439
440void ByteBuffer::Put(const ByteBuffer& byteBuffer)
441{
442    PutData(byteBuffer.GetBufferPtr(), byteBuffer.Remaining());
443}
444
445void ByteBuffer::PutData(const char data[], int32_t len)
446{
447    if (buffer != nullptr && data != nullptr && len > 0 && (limit - position) >= len) {
448        if (memcpy_s((buffer.get() + position), (limit - position), data, len) != EOK) {
449            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
450        } else {
451            position += len;
452        }
453    }
454}
455
456void ByteBuffer::PutData(int8_t data[], int32_t len)
457{
458    if (buffer != nullptr && data != nullptr && len > 0 && (limit - position) >= len) {
459        if (memcpy_s((buffer.get() + position), (limit - position), data, len) != EOK) {
460            SIGNATURE_TOOLS_LOGE("memcpy_s failed");
461        } else {
462            position += len;
463        }
464    }
465}
466
467void ByteBuffer::GetByte(int8_t data[], int32_t len)
468{
469    if (0 == memcpy_s(data, len, buffer.get() + position, len)) {
470        position = position + len;
471    }
472}
473
474void ByteBuffer::GetData(char data[], uint32_t len)
475{
476    if (0 == memcpy_s(data, len, buffer.get() + position, len)) {
477        position = position + len;
478    }
479}
480
481void ByteBuffer::GetData(int32_t offset, int8_t data[], uint32_t len)
482{
483    if (0 == memcpy_s(data, len, buffer.get() + offset, len)) {
484        position = position + len;
485    }
486}
487
488void ByteBuffer::SetPosition(int32_t pos)
489{
490    if (pos >= 0 && pos <= limit) {
491        position = pos;
492    }
493}
494
495ByteBuffer& ByteBuffer::slice_for_codesigning()
496{
497    if (position >= capacity || limit > capacity || position >= limit || buffer == nullptr) {
498        SIGNATURE_TOOLS_LOGE("position %d capacity %d limit %d error", position, capacity, limit);
499        return *this;
500    }
501    int32_t rem = (position <= limit ? limit - position : 0);
502
503    position = 0;
504    capacity = rem;
505    limit = rem;
506    return *this;
507}
508
509ByteBuffer& ByteBuffer::Slice()
510{
511    if (position >= capacity || limit > capacity || position >= limit || buffer == nullptr) {
512        SIGNATURE_TOOLS_LOGE("position %d capacity %d limit %d error",
513                             position, capacity, limit);
514        return *this;
515    }
516    int32_t newCapacity = limit - position;
517    auto newBuffer = make_shared_array<char>(newCapacity);
518    if (newBuffer == nullptr) {
519        SIGNATURE_TOOLS_LOGE("make_shared_array failed");
520        return *this;
521    }
522    if (memcpy_s(newBuffer.get(), newCapacity, buffer.get() + position, newCapacity) != RET_OK) {
523        SIGNATURE_TOOLS_LOGE("memcpy_s failed");
524        return *this;
525    }
526    buffer = std::move(newBuffer);
527    position = 0;
528    capacity = newCapacity;
529    limit = capacity;
530
531    return *this;
532}
533
534ByteBuffer* ByteBuffer::Duplicate()
535{
536    ByteBuffer* newBuffer = new ByteBuffer();
537    newBuffer->buffer = buffer;
538    newBuffer->limit = limit;
539    newBuffer->capacity = capacity;
540    newBuffer->position = position;
541    return newBuffer;
542}
543
544int32_t ByteBuffer::GetPosition() const
545{
546    return position;
547}
548
549int32_t ByteBuffer::GetLimit() const
550{
551    return limit;
552}
553
554void ByteBuffer::SetLimit(int32_t lim)
555{
556    if (lim <= capacity && lim >= position) {
557        limit = lim;
558    }
559}
560
561int32_t ByteBuffer::Remaining() const
562{
563    return position < limit ? limit - position : 0;
564}
565
566bool ByteBuffer::HasRemaining() const
567{
568    return position < limit;
569}
570
571void ByteBuffer::Clear()
572{
573    position = 0;
574    limit = capacity;
575}
576
577ByteBuffer& ByteBuffer::Flip()
578{
579    limit = position;
580    position = 0;
581    return *this;
582}
583
584bool ByteBuffer::IsEqual(const ByteBuffer& other)
585{
586    if (&other == this) {
587        return true;
588    }
589    if (capacity != other.GetCapacity() || other.GetBufferPtr() == nullptr || buffer == nullptr) {
590        SIGNATURE_TOOLS_LOGE("invalid input");
591        return false;
592    }
593    const char* otherBuffer = other.GetBufferPtr();
594    for (int32_t i = 0; i < capacity; i++) {
595        if (buffer.get()[i] != otherBuffer[i]) {
596            SIGNATURE_TOOLS_LOGE("diff value[%d]: %x %x",
597                                 i, buffer.get()[i], otherBuffer[i]);
598            return false;
599        }
600    }
601    return true;
602}
603
604bool ByteBuffer::IsEqual(const std::string& other)
605{
606    if (capacity != static_cast<int32_t>(other.size()) || buffer == nullptr) {
607        SIGNATURE_TOOLS_LOGE("invalid input");
608        return false;
609    }
610    for (int32_t i = 0; i < capacity; i++) {
611        if (buffer.get()[i] != other[i]) {
612            SIGNATURE_TOOLS_LOGE("diff value[%d]: %x %x",
613                                 i, buffer.get()[i], other[i]);
614            return false;
615        }
616    }
617    return true;
618}
619
620void ByteBuffer::SetCapacity(int32_t cap)
621{
622    if (buffer != nullptr) {
623        buffer = nullptr;
624        position = 0;
625        limit = 0;
626        capacity = 0;
627    }
628    Init(cap);
629}
630
631std::string ByteBuffer::ToString()
632{
633    return std::string(GetBufferPtr(), GetCapacity());
634}
635
636} // namespace SignatureTools
637} // namespace OHOS