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