Bug Summary

File:rootdir/src/RLE.cpp
Warning:line 148, column 17
Access of 'unsigned char' element in the heap area at index 0

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name RLE.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -D USE_WX_EXTENSIONS -I /usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.2 -I /usr/include/wx-3.2 -D _FILE_OFFSET_BITS=64 -D WXUSINGDLL -D __WXGTK__ -D wxUSE_GUI=0 -I ./libs -I ./include -I /usr/include/upnp -D ENABLE_UPNP=1 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-register -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-01-14-142724-17216-1 -x c++ RLE.cpp
1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5//
6// Any parts of this program derived from the xMule, lMule or eMule project,
7// or contributed by third-party developers are copyrighted by their
8// respective authors.
9//
10// This program is free software; you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation; either version 2 of the License, or
13// (at your option) any later version.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23//
24
25#include "RLE.h"
26#include "ArchSpecific.h"
27#include "ScopedPtr.h"
28#include <ec/cpp/ECTag.h> // Needed for CECTag
29
30/*
31 * RLE encoder implementation. This is RLE implementation for very specific
32 * purpose: encode DIFFERENCE between subsequent states of status bar.
33 *
34 * This difference is calculated by xor-ing with previous data
35 *
36 * We can't use implementation with "control char" since this encoder
37 * will process binary data - not ascii (or unicode) strings
38 */
39void RLE_Data::setup(int len, bool use_diff, uint8 * content)
40{
41 m_len = len;
42 m_use_diff = use_diff;
43
44 if (m_len) {
45 m_buff = new uint8[m_len];
46 if (content) {
47 memcpy(m_buff, content, m_len);
48 } else {
49 memset(m_buff, 0, m_len);
50 }
51 //
52 } else {
53 m_buff = 0;
54 }
55}
56
57RLE_Data &RLE_Data::operator=(const RLE_Data &obj)
58{
59 if (this == &obj)
60 return *this;
61
62 delete [] m_buff;
63 setup(obj.m_len, obj.m_use_diff, obj.m_buff);
64
65 return *this;
66}
67
68RLE_Data::~RLE_Data()
69{
70 delete [] m_buff;
71}
72
73void RLE_Data::ResetEncoder()
74{
75 delete m_buff;
76 m_len = 0;
77 m_buff = 0;
78}
79
80bool RLE_Data::Realloc(int size)
81{
82 if ( size == m_len ) {
83 return false;
84 }
85 if (size == 0) {
86 delete [] m_buff;
87 m_buff = 0;
88 m_len = 0;
89 return true;
90 }
91 uint8 *buff = new uint8[size];
92 if (m_len == 0) {
93 memset(buff, 0, size);
94 } else if ( size > m_len ) {
95 memset(buff + m_len, 0, size - m_len);
96 memcpy(buff, m_buff, m_len);
97 } else {
98 memcpy(buff, m_buff, size);
99 }
100 delete [] m_buff;
101 m_buff = buff;
102
103 m_len = size;
104 return true;
105}
106
107const uint8 *RLE_Data::Decode(const uint8 *buff, int len)
108{
109 uint8 * decBuf = m_len ? new uint8[m_len] : 0;
3
Assuming field 'm_len' is not equal to 0
4
'?' condition is true
110
111 // If data exceeds the buffer, switch to counting only.
112 // Then resize and make a second pass.
113 for (bool overrun = true; overrun;) {
5
Loop condition is true. Entering loop body
23
Loop condition is false. Execution continues on line 146
114 overrun = false;
115 int j = 0;
116 for (int i = 0; i
11.1
'i' is < 'len'
< len
;) {
6
Assuming 'i' is < 'len'
17
Assuming 'i' is >= 'len'
18
Loop condition is false. Execution continues on line 134
117 if (i < len - 2 && buff[i+1] == buff[i]) {
7
Assuming the condition is true
8
Assuming the condition is false
9
Taking false branch
12
Assuming the condition is true
13
Assuming the condition is true
14
Taking true branch
118 // This is a sequence.
119 uint8 seqLen = buff[i + 2];
120 if (j + seqLen <= m_len) {
15
Assuming the condition is true
16
Taking true branch
121 memset(decBuf + j, buff[i], seqLen);
122 }
123 j += seqLen;
124 i += 3;
125 } else {
126 // This is a single byte.
127 if (j < m_len) {
10
Assuming 'j' is >= field 'm_len'
11
Taking false branch
128 decBuf[j] = buff[i];
129 }
130 j++;
131 i++;
132 }
133 }
134 if (j != m_len) {
19
Assuming 'j' is not equal to field 'm_len'
20
Taking true branch
135 overrun = j > m_len; // overrun, make a second pass
21
Assuming 'j' is <= field 'm_len'
136 Realloc(j); // size has changed, adjust
137 if (overrun
21.1
'overrun' is false
) {
22
Taking false branch
138 delete[] decBuf;
139 decBuf = new uint8[m_len];
140 }
141 }
142 }
143 //
144 // Recreate data from diff
145 //
146 if ( m_use_diff ) {
24
Assuming field 'm_use_diff' is true
25
Taking true branch
147 for (int k = 0; k
25.1
'k' is < field 'm_len'
< m_len; k++) {
26
Loop condition is true. Entering loop body
148 m_buff[k] ^= decBuf[k];
27
Access of 'unsigned char' element in the heap area at index 0
149 }
150 } else {
151 memcpy(m_buff, decBuf, m_len);
152 }
153 delete[] decBuf;
154 return m_buff;
155}
156
157const uint8 * RLE_Data::Encode(const uint8 *data, int inlen, int &outlen, bool &changed)
158{
159 changed = Realloc(inlen); // adjust size if necessary
160
161 if (m_len == 0) {
162 outlen = 0;
163 return NULL__null;
164 }
165 //
166 // calculate difference from prev
167 //
168 if ( m_use_diff ) {
169 for (int i = 0; i < m_len; i++) {
170 m_buff[i] ^= data[i];
171 if (m_buff[i]) {
172 changed = true;
173 }
174 }
175 } else {
176 memcpy(m_buff, data, m_len);
177 changed = true;
178 }
179
180 //
181 // now RLE
182 //
183 // In worst case 2-byte sequence is encoded as 3. So, data can grow by 50%.
184 uint8 * enc_buff = new uint8[m_len * 3/2 + 1];
185 int i = 0, j = 0;
186 while ( i != m_len ) {
187 uint8 curr_val = m_buff[i];
188 int seq_start = i;
189 while ( (i != m_len) && (curr_val == m_buff[i]) && ((i - seq_start) < 0xff)) {
190 i++;
191 }
192 if (i - seq_start > 1) {
193 // if there's 2 or more equal vals - put it twice in stream
194 enc_buff[j++] = curr_val;
195 enc_buff[j++] = curr_val;
196 enc_buff[j++] = i - seq_start;
197 } else {
198 // single value - put it as is
199 enc_buff[j++] = curr_val;
200 }
201 }
202
203 outlen = j;
204
205 //
206 // If using differential encoder, remember current data for
207 // later use
208 if ( m_use_diff ) {
209 memcpy(m_buff, data, m_len);
210 }
211
212 return enc_buff;
213}
214
215const uint8 * RLE_Data::Encode(const ArrayOfUInts16 &data, int &outlen, bool &changed)
216{
217 // To encode, first copy the UInts16 to a uint8 array
218 // and limit them to 0xff.
219 // The encoded size is the size of data.
220 int size = (int) data.size();
221 if (size == 0) {
222 return Encode(0, 0, outlen, changed);
223 }
224 CScopedArray<uint8> buf(size);
225 uint8 * bufPtr = buf.get();
226
227 for (int i = 0; i < size; i++) {
228 uint16 ui = data[i];
229 bufPtr[i] = (ui > 0xff) ? 0xff : (uint8) ui;
230 }
231 return Encode(bufPtr, size, outlen, changed);
232}
233
234const uint8 * RLE_Data::Encode(const ArrayOfUInts64 &data, int &outlen, bool &changed)
235{
236 // uint64 is copied to a uint8 buffer
237 // first all low bytes, then all second low bytes and so on
238 // so initial RLE will benefit from high bytes being equal (zero)
239 // 0x000003045A6A7A8A, 0x000003045B6B7B8B
240 // 8A8B7A7B6A6B5A5B0404030300000000
241 int size = (int) data.size();
242 if (size == 0) {
243 return Encode(0, 0, outlen, changed);
244 }
245 CScopedArray<uint8> buf(size * 8);
246 uint8 * bufPtr = buf.get();
247 for (int i = 0; i < size; i++) {
248 uint64 u = data[i];
249 for (int j = 0; j < 8; j++) {
250 bufPtr[i + j * size] = u & 0xff;
251 u >>= 8;
252 }
253 }
254 return Encode(bufPtr, size * 8, outlen, changed);
255}
256
257void RLE_Data::Decode(const uint8 *data, int len, ArrayOfUInts64 &outdata)
258{
259 const uint8 * decoded = Decode(data, len);
2
Calling 'RLE_Data::Decode'
260 wxASSERT(m_len % 8 == 0)do { if ( m_len % 8 == 0 ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("RLE.cpp", 260, __FUNCTION__, "m_len % 8 == 0", (
const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
261 int size = m_len / 8;
262 outdata.resize(size);
263 for (int i = 0; i < size; i++) {
264 uint64 u = 0;
265 for (int j = 8; j--;) {
266 u <<= 8;
267 u |= decoded[i + j * size];
268 }
269 outdata[i] = u;
270 }
271}
272
273void PartFileEncoderData::DecodeParts(const CECTag * tag, ArrayOfUInts16 &outdata)
274{
275 const uint8 * buf = m_part_status.Decode((uint8 *)tag->GetTagData(), tag->GetTagDataLen());
276 int size = m_part_status.Size();
277 outdata.resize(size);
278 for (int i = 0; i < size; i++) {
279 outdata[i] = buf[i];
280 }
281}
282
283void PartFileEncoderData::DecodeGaps(const CECTag * tag, ArrayOfUInts64 &outdata)
284{
285 m_gap_status.Decode((uint8 *)tag->GetTagData(), tag->GetTagDataLen(), outdata);
286}
287
288void PartFileEncoderData::DecodeReqs(const CECTag * tag, ArrayOfUInts64 &outdata)
289{
290 m_req_status.Decode((uint8 *)tag->GetTagData(), tag->GetTagDataLen(), outdata);
1
Calling 'RLE_Data::Decode'
291}
292
293
294// File_checked_for_headers