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
16 #include <cinttypes>
17 #include <algorithm>
18 #include <mutex>
19 #include <stdexcept>
20 #include <string>
21
22 #include "random_access_file_input.h"
23
24 namespace OHOS {
25 namespace SignatureTools {
RandomAccessFileInput(RandomAccessFile& file)26 RandomAccessFileInput::RandomAccessFileInput(RandomAccessFile& file) : file(file),
27 startIndex(0), size(-1)
28 {
29 }
30
RandomAccessFileInput(RandomAccessFile& file, int64_t offset, int64_t size)31 RandomAccessFileInput::RandomAccessFileInput(RandomAccessFile& file, int64_t offset, int64_t size)
32 : file(file), startIndex(offset), size(size)
33 {
34 if (offset < 0) {
35 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64, offset);
36 return;
37 }
38 if (size < 0) {
39 SIGNATURE_TOOLS_LOGE("out of range: size %" PRId64, size);
40 return;
41 }
42 }
43
Size()44 int64_t RandomAccessFileInput::Size()
45 {
46 if (size == -1) {
47 return file.GetLength();
48 }
49 return size;
50 }
51
CopyTo(int64_t offset, int size, ByteBuffer& buffer)52 bool RandomAccessFileInput::CopyTo(int64_t offset, int size, ByteBuffer& buffer)
53 {
54 int64_t srcSize = Size();
55 if (!CheckBoundValid(offset, size, srcSize)) {
56 return false;
57 }
58 if (size == 0) {
59 SIGNATURE_TOOLS_LOGE("Copy size is equal to 0");
60 return false;
61 }
62 if (size > buffer.Remaining()) {
63 SIGNATURE_TOOLS_LOGE("The length size passed in is greater than the reserved length of ByteBuffer");
64 return false;
65 }
66 int64_t offsetInFile = startIndex + offset;
67 int remaining = size;
68 int originalLimit = buffer.GetLimit();
69
70 buffer.SetLimit(buffer.GetPosition() + size);
71 int64_t readSize;
72 while (remaining > 0) {
73 {
74 std::mutex tmpMutex;
75 std::scoped_lock lock(tmpMutex);
76 readSize = file.ReadFileFullyFromOffset(buffer, offsetInFile);
77 }
78 offsetInFile += readSize;
79 remaining -= readSize;
80 }
81 int cap = buffer.GetCapacity();
82 buffer.SetPosition(cap);
83 buffer.SetLimit(originalLimit);
84 return true;
85 }
86
CreateByteBuffer(int64_t offset, int size)87 ByteBuffer RandomAccessFileInput::CreateByteBuffer(int64_t offset, int size)
88 {
89 ByteBuffer byteBuffer;
90 if (size < 0) {
91 SIGNATURE_TOOLS_LOGE("IndexOutOfBounds: The created ByteBuffer size %d is less than 0", size);
92 return byteBuffer;
93 }
94
95 byteBuffer.SetCapacity(size);
96 if (!CopyTo(offset, size, byteBuffer)) {
97 byteBuffer.SetCapacity(0);
98 return byteBuffer;
99 }
100
101 return byteBuffer.Flip();
102 }
103
Slice(int64_t offset, int64_t size)104 DataSource* RandomAccessFileInput::Slice(int64_t offset, int64_t size)
105 {
106 int64_t srcSize = Size();
107 if (!CheckBoundValid(offset, size, srcSize)) {
108 return nullptr;
109 }
110 if (offset == 0 && size == srcSize) {
111 SIGNATURE_TOOLS_LOGI("offset: 0, size: %" PRId64 ", it will return itself", size);
112 return new FileDataSource(file, startIndex, size, 0);
113 }
114 return new FileDataSource(file, offset, size, 0);
115 }
116
CheckBoundValid(int64_t offset, int64_t size, int64_t sourceSize)117 bool RandomAccessFileInput::CheckBoundValid(int64_t offset, int64_t size, int64_t sourceSize)
118 {
119 if (offset < 0) {
120 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64, offset);
121 return false;
122 }
123 if (size < 0) {
124 SIGNATURE_TOOLS_LOGE("out of range: size %" PRId64, size);
125 return false;
126 }
127 if (offset > sourceSize) {
128 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64 " is greater than sourceSize %" PRId64,
129 offset, sourceSize);
130 return false;
131 }
132 int64_t endOffset = offset + size;
133 if (endOffset < offset) {
134 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64 " add size %" PRId64 " is overflow",
135 offset, size);
136 return false;
137 }
138 if (endOffset > sourceSize) {
139 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64 " add size %" PRId64 " is greater than "
140 "sourceSize %" PRId64, offset, size, sourceSize);
141 return false;
142 }
143 return true;
144 }
145 } // namespace SignatureTools
146 } // namespace OHOS