Bug Summary

File:rootdir/src/RLE.cpp
Warning:line 128, column 16
Array access (from variable 'decBuf') results in a null pointer dereference

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/2024-12-16-222823-17165-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 0
4
'?' condition is false
5
'decBuf' initialized to a null pointer value
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;) {
6
Loop condition is true. Entering loop body
114 overrun = false;
115 int j = 0;
116 for (int i = 0; i < len;) {
7
Assuming 'i' is < 'len'
13
Assuming 'i' is < 'len'
19
Assuming 'i' is < 'len'
22
Assuming 'i' is < 'len'
117 if (i < len - 2 && buff[i+1] == buff[i]) {
8
Assuming the condition is true
9
Assuming the condition is true
10
Taking true branch
14
Assuming the condition is true
15
Assuming the condition is true
16
Taking true branch
20
Assuming the condition is false
118 // This is a sequence.
119 uint8 seqLen = buff[i + 2];
120 if (j + seqLen <= m_len) {
11
Assuming the condition is false
12
Taking false branch
17
Assuming the condition is false
18
Taking false 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
20.1
'j' is >= field 'm_len'
< m_len
) {
21
Taking false branch
23
Assuming 'j' is < field 'm_len'
24
Taking true branch
128 decBuf[j] = buff[i];
25
Array access (from variable 'decBuf') results in a null pointer dereference
129 }
130 j++;
131 i++;
132 }
133 }
134 if (j != m_len) {
135 overrun = j > m_len; // overrun, make a second pass
136 Realloc(j); // size has changed, adjust
137 if (overrun) {
138 delete[] decBuf;
139 decBuf = new uint8[m_len];
140 }
141 }
142 }
143 //
144 // Recreate data from diff
145 //
146 if ( m_use_diff ) {
147 for (int k = 0; k < m_len; k++) {
148 m_buff[k] ^= decBuf[k];
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