Bug Summary

File:rootdir/src/Packet.cpp
Warning:line 171, column 32
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

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 Packet.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-17-081402-14897-1 -x c++ Packet.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// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6//
7// Any parts of this program derived from the xMule, lMule or eMule project,
8// or contributed by third-party developers are copyrighted by their
9// respective authors.
10//
11// This program is free software; you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation; either version 2 of the License, or
14// (at your option) any later version.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24//
25
26#include <zlib.h> // Needed for uLongf
27
28#include "Packet.h" // Interface declarations
29
30#include <protocol/Protocols.h>
31
32#include "Logger.h" // Needed for AddDebugLogLineN
33#include "MemFile.h" // Needed for CMemFile
34#include "OtherStructs.h" // Needed for Header_Struct
35#include "ArchSpecific.h" // Needed for ENDIAN_*
36
37// Copy constructor
38CPacket::CPacket(CPacket &p)
39{
40 size = p.size;
41 opcode = p.opcode;
42 prot = p.prot;
43 m_bSplitted = p.m_bSplitted;
44 m_bLastSplitted = p.m_bLastSplitted;
45 m_bPacked = p.m_bPacked;
46 m_bFromPF = p.m_bFromPF;
47 memcpy(head, p.head, sizeof head);
48 tempbuffer = NULL__null;
49 if (p.completebuffer) {
50 completebuffer = new uint8_t[size + 10];;
51 pBuffer = completebuffer + sizeof(Header_Struct);
52 } else {
53 completebuffer = NULL__null;
54 if (p.pBuffer) {
55 pBuffer = new uint8_t[size];
56 } else {
57 pBuffer = NULL__null;
58 }
59 }
60 if (pBuffer)
61 memcpy( pBuffer, p.pBuffer, size );
62}
63
64CPacket::CPacket(uint8 protocol)
65{
66 size = 0;
67 opcode = 0;
68 prot = protocol;
69 m_bSplitted = false;
70 m_bLastSplitted = false;
71 m_bPacked = false;
72 m_bFromPF = false;
73 memset(head, 0, sizeof head);
74 tempbuffer = NULL__null;
75 completebuffer = NULL__null;
76 pBuffer = NULL__null;
77}
78
79// only used for receiving packets
80CPacket::CPacket(uint8_t* rawHeader, uint8_t *buf)
81{
82 memset(head, 0, sizeof head);
83 Header_Struct* header = reinterpret_cast<Header_Struct*>(rawHeader);
84 size = ENDIAN_SWAP_32(header->packetlength)((header->packetlength)) - 1;
85 opcode = header->command;
86 prot = header->eDonkeyID;
87 m_bSplitted = false;
88 m_bLastSplitted = false;
89 m_bPacked = false;
90 m_bFromPF = false;
91 tempbuffer = NULL__null;
92 completebuffer = NULL__null;
93 pBuffer = buf;
94}
95
96CPacket::CPacket(const CMemFile& datafile, uint8 protocol, uint8 ucOpcode)
97{
98 size = datafile.GetLength();
99 opcode = ucOpcode;
100 prot = protocol;
101 m_bSplitted = false;
102 m_bLastSplitted = false;
103 m_bPacked = false;
104 m_bFromPF = false;
105 memset(head, 0, sizeof head);
106 tempbuffer = NULL__null;
107 completebuffer = new uint8_t[size + sizeof(Header_Struct)/*Why this 4?*/];
108 pBuffer = completebuffer + sizeof(Header_Struct);
109
110 // Write contents of MemFile to buffer (while keeping original position in file)
111 off_t position = datafile.GetPosition();
112 datafile.Seek(0, wxFromStart);
113 datafile.Read(pBuffer, size);
114 datafile.Seek(position, wxFromStart);
115}
116
117CPacket::CPacket(int8 in_opcode, uint32 in_size, uint8 protocol, bool bFromPF)
118{
119 size = in_size;
120 opcode = in_opcode;
121 prot = protocol;
122 m_bSplitted = false;
123 m_bLastSplitted = false;
124 m_bPacked = false;
125 m_bFromPF = bFromPF;
126 memset(head, 0, sizeof head);
127 tempbuffer = NULL__null;
128 if (in_size) {
129 completebuffer = new uint8_t[in_size + sizeof(Header_Struct) + 4 /*Why this 4?*/];
130 pBuffer = completebuffer + sizeof(Header_Struct);
131 memset(completebuffer, 0, in_size + sizeof(Header_Struct) + 4 /*Why this 4?*/);
132 } else {
133 completebuffer = NULL__null;
134 pBuffer = NULL__null;
135 }
136}
137
138// only used for splitted packets!
139CPacket::CPacket(uint8_t* pPacketPart, uint32 nSize, bool bLast, bool bFromPF)
140{
141 size = nSize - sizeof(Header_Struct);
142 opcode = 0;
143 prot = 0;
144 m_bSplitted = true;
145 m_bLastSplitted = bLast;
146 m_bPacked = false;
147 m_bFromPF = bFromPF;
148 memset(head, 0, sizeof head);
149 tempbuffer = NULL__null;
150 completebuffer = pPacketPart;
151 pBuffer = NULL__null;
152}
153
154CPacket::~CPacket()
155{
156 // Never deletes pBuffer when completebuffer is not NULL
157 if (completebuffer) {
158 delete [] completebuffer;
159 } else if (pBuffer) {
160 // On the other hand, if completebuffer is NULL and pBuffer is not NULL
161 delete [] pBuffer;
162 }
163
164 if (tempbuffer) {
165 delete [] tempbuffer;
166 }
167}
168
169uint32 CPacket::GetPacketSizeFromHeader(const uint8_t* rawHeader)
170{
171 const Header_Struct* header = reinterpret_cast<const Header_Struct*>(rawHeader);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
172 uint32 size = ENDIAN_SWAP_32(header->packetlength)((header->packetlength));
173 if (size < 1 || size >= 0x7ffffff0u)
174 return 0;
175 return size - 1;
176}
177
178void CPacket::CopyToDataBuffer(unsigned int offset, const uint8_t* data, unsigned int n)
179{
180 wxASSERT(offset + n <= size + 1)do { if ( offset + n <= size + 1 ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Packet.cpp", 180, __FUNCTION__, "offset + n <= size + 1"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
181 memcpy(pBuffer + offset, data, n);
182}
183
184uint8_t* CPacket::GetPacket() {
185 if (completebuffer) {
186 if (!m_bSplitted) {
187 memcpy(completebuffer, GetHeader(), sizeof(Header_Struct));
188 }
189 return completebuffer;
190 } else {
191 if (tempbuffer){
192 delete [] tempbuffer;
193 tempbuffer = NULL__null;
194 }
195 tempbuffer = new uint8_t[size + sizeof(Header_Struct) + 4 /* why this 4?*/];
196 memcpy(tempbuffer , GetHeader(), sizeof(Header_Struct));
197 memcpy(tempbuffer + sizeof(Header_Struct), pBuffer , size);
198 return tempbuffer;
199 }
200}
201
202uint8_t* CPacket::DetachPacket() {
203 if (completebuffer) {
204 if (!m_bSplitted) {
205 memcpy(completebuffer, GetHeader(), sizeof(Header_Struct));
206 }
207 uint8_t* result = completebuffer;
208 completebuffer = pBuffer = NULL__null;
209 return result;
210 } else{
211 if (tempbuffer){
212 delete[] tempbuffer;
213 tempbuffer = NULL__null;
214 }
215 tempbuffer = new uint8_t[size+sizeof(Header_Struct)+4 /* Why this 4?*/];
216 memcpy(tempbuffer,GetHeader(),sizeof(Header_Struct));
217 memcpy(tempbuffer+sizeof(Header_Struct),pBuffer,size);
218 uint8_t* result = tempbuffer;
219 tempbuffer = 0;
220 return result;
221 }
222}
223
224uint8_t* CPacket::GetHeader() {
225 wxASSERT( !m_bSplitted )do { if ( !m_bSplitted ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("Packet.cpp", 225, __FUNCTION__, "!m_bSplitted",
(const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
226
227 Header_Struct* header = reinterpret_cast<Header_Struct*>(head);
228 header->command = opcode;
229 header->eDonkeyID = prot;
230 header->packetlength = ENDIAN_SWAP_32(size + 1)((size + 1));
231
232 return head;
233}
234
235uint8_t* CPacket::GetUDPHeader() {
236 wxASSERT( !m_bSplitted )do { if ( !m_bSplitted ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("Packet.cpp", 236, __FUNCTION__, "!m_bSplitted",
(const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
237
238 memset(head, 0, 6);
239 UDP_Header_Struct* header = reinterpret_cast<UDP_Header_Struct*>(head);
240 header->eDonkeyID = prot;
241 header->command = opcode;
242
243 return head;
244}
245
246
247void CPacket::PackPacket()
248{
249 wxASSERT(!m_bSplitted)do { if ( !m_bSplitted ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("Packet.cpp", 249, __FUNCTION__, "!m_bSplitted",
(const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
250
251 uLongf newsize = size + 300;
252 uint8_t* output = new uint8_t[newsize];
253
254 uint16 result = compress2(output, &newsize, pBuffer, size, Z_BEST_COMPRESSION9);
255
256 if (result != Z_OK0 || size <= newsize) {
257 delete[] output;
258 return;
259 }
260
261 if (prot == OP_KADEMLIAHEADER) {
262 prot = OP_KADEMLIAPACKEDPROT;
263 } else {
264 prot = OP_PACKEDPROT;
265 }
266
267 memcpy(pBuffer, output, newsize);
268 delete[] output;
269 m_bPacked = true;
270
271 size = newsize;
272}
273
274
275bool CPacket::UnPackPacket(uint32 uMaxDecompressedSize) {
276 wxASSERT( prot == OP_PACKEDPROT || prot == OP_ED2KV2PACKEDPROT)do { if ( prot == OP_PACKEDPROT || prot == OP_ED2KV2PACKEDPROT
) { } else if ( wxTheAssertHandler && (wxOnAssert("Packet.cpp"
, 276, __FUNCTION__, "prot == OP_PACKEDPROT || prot == OP_ED2KV2PACKEDPROT"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
277 // OP_ED2KV2PACKEDPROT is experimental aMule test code,
278 // this should not happen yet. Leave a warning in the log.
279 if (prot == OP_ED2KV2PACKEDPROT) {
280 AddDebugLogLineN(logPacketErrors,do {} while (false)
281 wxT("Received OP_ED2KV2PACKEDPROT."))do {} while (false);
282 }
283
284 uint32 nNewSize = size * 10 + 300;
285
286 if (nNewSize > uMaxDecompressedSize){
287 nNewSize = uMaxDecompressedSize;
288 }
289
290 uint8_t* unpack = new uint8_t[nNewSize];
291 uLongf unpackedsize = nNewSize;
292 uint16 result = uncompress(unpack, &unpackedsize, pBuffer, size);
293
294 if (result == Z_OK0) {
295 wxASSERT( completebuffer == NULL )do { if ( completebuffer == __null ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Packet.cpp", 295, __FUNCTION__, "completebuffer == __null"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
296 wxASSERT( pBuffer != NULL )do { if ( pBuffer != __null ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Packet.cpp", 296, __FUNCTION__, "pBuffer != __null"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
297
298 size = unpackedsize;
299 delete[] pBuffer;
300 pBuffer = unpack;
301 prot = OP_EMULEPROT;
302 return true;
303 }
304
305 delete[] unpack;
306 return false;
307}
308
309
310void CPacket::Copy16ToDataBuffer(const void* data)
311{
312 md4cpy(pBuffer, data);
313}
314
315
316void CPacket::CopyUInt32ToDataBuffer(uint32 data, unsigned int offset)
317{
318 wxCHECK_RET(offset <= size - sizeof(uint32), wxT("Bad offset in CopyUInt32ToDataBuffer."))if ( offset <= size - sizeof(uint32) ) {} else { do { if (
wxTheAssertHandler && (wxOnAssert("Packet.cpp", 318,
__FUNCTION__, "\"offset <= size - sizeof(uint32)\"", L"Bad offset in CopyUInt32ToDataBuffer."
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 ); return; } struct wxDummyCheckStruct318
;
319 PokeUInt32( pBuffer + offset, data );
320}
321// File_checked_for_headers