Bug Summary

File:rootdir/src/Logger.cpp
Warning:line 184, column 9
Access of 'g_debugcats' at an overflowing index, while it holds only 40 'class CDebugCategory' elements

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 Logger.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/include/upnp -D ENABLE_UPNP=1 -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 ENABLE_IP2COUNTRY=1 -I ./libs -I libs -I ./include -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-05-184004-17430-1 -x c++ Logger.cpp
1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2005-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 "Logger.h"
26#include "amule.h"
27#include "Preferences.h"
28#include <common/Macros.h>
29#include <common/MacrosProgramSpecific.h>
30#include <sstream>
31#include <wx/tokenzr.h>
32#include <wx/wfstream.h>
33#include <wx/sstream.h>
34#include <wx/filename.h>
35
36
37DEFINE_LOCAL_EVENT_TYPE(MULE_EVT_LOGLINE)const wxEventType MULE_EVT_LOGLINE = wxNewEventType();
38
39
40CDebugCategory g_debugcats[] = {
41 CDebugCategory( logGeneral, wxT("General")L"General" ),
42 CDebugCategory( logHasher, wxT("Hasher")L"Hasher" ),
43 CDebugCategory( logClient, wxT("ED2k Client")L"ED2k Client" ),
44 CDebugCategory( logLocalClient, wxT("Local Client Protocol")L"Local Client Protocol" ),
45 CDebugCategory( logRemoteClient, wxT("Remote Client Protocol")L"Remote Client Protocol" ),
46 CDebugCategory( logPacketErrors, wxT("Packet Parsing Errors")L"Packet Parsing Errors" ),
47 CDebugCategory( logCFile, wxT("CFile")L"CFile" ),
48 CDebugCategory( logFileIO, wxT("FileIO")L"FileIO" ),
49 CDebugCategory( logZLib, wxT("ZLib")L"ZLib" ),
50 CDebugCategory( logAICHThread, wxT("AICH-Hasher")L"AICH-Hasher" ),
51 CDebugCategory( logAICHTransfer, wxT("AICH-Transfer")L"AICH-Transfer" ),
52 CDebugCategory( logAICHRecovery, wxT("AICH-Recovery")L"AICH-Recovery" ),
53 CDebugCategory( logListenSocket, wxT("ListenSocket")L"ListenSocket" ),
54 CDebugCategory( logCredits, wxT("Credits")L"Credits" ),
55 CDebugCategory( logClientUDP, wxT("ClientUDPSocket")L"ClientUDPSocket" ),
56 CDebugCategory( logDownloadQueue, wxT("DownloadQueue")L"DownloadQueue" ),
57 CDebugCategory( logIPFilter, wxT("IPFilter")L"IPFilter" ),
58 CDebugCategory( logKnownFiles, wxT("KnownFileList")L"KnownFileList" ),
59 CDebugCategory( logPartFile, wxT("PartFiles")L"PartFiles" ),
60 CDebugCategory( logSHAHashSet, wxT("SHAHashSet")L"SHAHashSet" ),
61 CDebugCategory( logServer, wxT("Servers")L"Servers" ),
62 CDebugCategory( logProxy, wxT("Proxy")L"Proxy" ),
63 CDebugCategory( logSearch, wxT("Searching")L"Searching" ),
64 CDebugCategory( logServerUDP, wxT("ServerUDP")L"ServerUDP" ),
65 CDebugCategory( logClientKadUDP, wxT("Client Kademlia UDP")L"Client Kademlia UDP" ),
66 CDebugCategory( logKadSearch, wxT("Kademlia Search")L"Kademlia Search" ),
67 CDebugCategory( logKadRouting, wxT("Kademlia Routing")L"Kademlia Routing" ),
68 CDebugCategory( logKadIndex, wxT("Kademlia Indexing")L"Kademlia Indexing" ),
69 CDebugCategory( logKadMain, wxT("Kademlia Main Thread")L"Kademlia Main Thread" ),
70 CDebugCategory( logKadPrefs, wxT("Kademlia Preferences")L"Kademlia Preferences" ),
71 CDebugCategory( logPfConvert, wxT("PartFileConvert")L"PartFileConvert" ),
72 CDebugCategory( logMuleUDP, wxT("MuleUDPSocket" )L"MuleUDPSocket" ),
73 CDebugCategory( logThreads, wxT("ThreadScheduler" )L"ThreadScheduler" ),
74 CDebugCategory( logUPnP, wxT("Universal Plug and Play" )L"Universal Plug and Play" ),
75 CDebugCategory( logKadUdpFwTester, wxT("Kademlia UDP Firewall Tester")L"Kademlia UDP Firewall Tester" ),
76 CDebugCategory( logKadPacketTracking, wxT("Kademlia Packet Tracking")L"Kademlia Packet Tracking" ),
77 CDebugCategory( logKadEntryTracking, wxT("Kademlia Entry Tracking")L"Kademlia Entry Tracking" ),
78 CDebugCategory( logEC, wxT("External Connect")L"External Connect" ),
79 CDebugCategory( logHTTP, wxT("HTTP")L"HTTP" ),
80 CDebugCategory( logAsio, wxT("Asio Sockets")L"Asio Sockets" )
81};
82
83
84const int categoryCount = itemsof(g_debugcats)(sizeof(g_debugcats) / sizeof(g_debugcats[0]));
85
86
87
88#ifdef __DEBUG__
89bool CLogger::IsEnabled( DebugType type ) const
90{
91 int index = (int)type;
92
93 if ( index >= 0 && index < categoryCount ) {
94 const CDebugCategory& cat = g_debugcats[ index ];
95 wxASSERT( type == cat.GetType() )do { if ( type == cat.GetType() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Logger.cpp", 95, __FUNCTION__, "type == cat.GetType()"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
96
97 return ( cat.IsEnabled() && thePrefs::GetVerbose() );
98 }
99
100 wxFAILdo { if ( wxTheAssertHandler && (wxOnAssert("Logger.cpp"
, 100, __FUNCTION__, "\"Assert failure\"", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
101 return false;
102}
103#endif
104
105
106void CLogger::SetEnabled( DebugType type, bool enabled )
107{
108 int index = (int)type;
109
110 if ( index >= 0 && index < categoryCount ) {
111 CDebugCategory& cat = g_debugcats[ index ];
112 wxASSERT( type == cat.GetType() )do { if ( type == cat.GetType() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Logger.cpp", 112, __FUNCTION__, "type == cat.GetType()"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
113
114 cat.SetEnabled( enabled );
115 } else {
116 wxFAILdo { if ( wxTheAssertHandler && (wxOnAssert("Logger.cpp"
, 116, __FUNCTION__, "\"Assert failure\"", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
117 }
118}
119
120
121void CLogger::AddLogLine(
122 const wxString& DEBUG_ONLY(file),
123 int DEBUG_ONLY(line),
124 bool critical,
125 DebugType type,
126 const wxString &str,
127 bool toStdout,
128 bool toGUI)
129{
130 wxString msg(str);
131// handle Debug messages
132 if (type != logStandard) {
133 if (!critical && !IsEnabled(type)) {
134 return;
135 }
136 if (!critical && thePrefs::GetVerboseLogfile()) {
137 // print non critical debug messages only to the logfile
138 toGUI = false;
139 }
140 int index = (int)type;
141
142 if ( index >= 0 && index < categoryCount ) {
143 const CDebugCategory& cat = g_debugcats[ index ];
144 wxASSERT(type == cat.GetType())do { if ( type == cat.GetType() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Logger.cpp", 144, __FUNCTION__, "type == cat.GetType()"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
145
146 msg = cat.GetName() + wxT(": ")L": " + msg;
147 } else {
148 wxFAILdo { if ( wxTheAssertHandler && (wxOnAssert("Logger.cpp"
, 148, __FUNCTION__, "\"Assert failure\"", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
149 }
150 }
151
152#ifdef __DEBUG__
153 if (line) {
154 msg = file.AfterLast(wxFileName::GetPathSeparator()).AfterLast(wxT('/')L'/') << wxT("(")L"(" << line << wxT("): ")L"): " + msg;
155 }
156#endif
157
158 if (toGUI && !wxThread::IsMain()) {
159 // put to background
160 CLoggingEvent Event(critical, toStdout, toGUI, msg);
161 AddPendingEvent(Event);
162 } else {
163 // Try to handle events immediately when possible (to save to file).
164 DoLines(msg, critical, toStdout, toGUI);
165 }
166}
167
168
169void CLogger::AddLogLine(
170 const wxString &file,
171 int line,
172 bool critical,
173 DebugType type,
174 const std::ostringstream &msg)
175{
176 AddLogLine(file, line, critical, type, wxString(char2unicode(msg.str().c_str())));
177}
178
179
180const CDebugCategory& CLogger::GetDebugCategory( int index )
181{
182 wxASSERT( index >= 0 && index < categoryCount )do { if ( index >= 0 && index < categoryCount )
{ } else if ( wxTheAssertHandler && (wxOnAssert("Logger.cpp"
, 182, __FUNCTION__, "index >= 0 && index < categoryCount"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
1
Assuming 'index' is >= 0
2
Assuming 'index' is >= 'categoryCount'
3
Taking false branch
4
Assuming 'wxTheAssertHandler' is null
5
Loop condition is false. Exiting loop
183
184 return g_debugcats[ index ];
6
Access of 'g_debugcats' at an overflowing index, while it holds only 40 'class CDebugCategory' elements
185}
186
187
188unsigned int CLogger::GetDebugCategoryCount()
189{
190 return categoryCount;
191}
192
193
194bool CLogger::OpenLogfile(const wxString & name)
195{
196 applog = new wxFFileOutputStream(name);
197 bool ret = applog->Ok();
198 if (ret) {
199 FlushApplog();
200 m_LogfileName = name;
201 } else {
202 CloseLogfile();
203 }
204 return ret;
205}
206
207
208void CLogger::CloseLogfile()
209{
210 delete applog;
211 applog = NULL__null;
212 m_LogfileName.Clear();
213}
214
215
216void CLogger::OnLoggingEvent(class CLoggingEvent& evt)
217{
218 DoLines(evt.Message(), evt.IsCritical(), evt.ToStdout(), evt.ToGUI());
219}
220
221
222void CLogger::DoLines(const wxString & lines, bool critical, bool toStdout, bool toGUI)
223{
224 // Remove newspace at end
225 wxString bufferline = lines.Strip(wxString::trailing);
226
227 // Create the timestamp
228 wxString stamp = wxDateTime::Now().FormatISODate() + wxT(" ")L" " + wxDateTime::Now().FormatISOTime()
229#ifdef CLIENT_GUI
230 + wxT(" (remote-GUI): ")L" (remote-GUI): ";
231#else
232 + wxT(": ")L": ";
233#endif
234
235 // critical lines get a ! prepended, ordinary lines a blank
236 // logfile-only lines get a . to prevent transmission on EC
237 wxString prefix = !toGUI ? wxT(".")L"." : (critical ? wxT("!")L"!" : wxT(" ")L" ");
238
239 if ( bufferline.IsEmpty() ) {
240 // If it's empty we just write a blank line with no timestamp.
241 DoLine(wxT(" \n")L" \n", toStdout, toGUI);
242 } else {
243 // Split multi-line messages into individual lines
244 wxStringTokenizer tokens( bufferline, wxT("\n")L"\n" );
245 while ( tokens.HasMoreTokens() ) {
246 wxString fullline = prefix + stamp + tokens.GetNextToken() + wxT("\n")L"\n";
247 DoLine(fullline, toStdout, toGUI);
248 }
249 }
250}
251
252
253void CLogger::DoLine(const wxString & line, bool toStdout, bool GUI_ONLY(toGUI)toGUI)
254{
255 {
256 wxMutexLocker lock(m_lineLock);
257 ++m_count;
258
259 // write to logfile
260 m_ApplogBuf += line;
261 FlushApplog();
262
263 // write to Stdout
264 if (m_StdoutLog || toStdout) {
265 printf("%s", (const char*)unicode2char(line));
266 }
267 }
268#ifndef AMULE_DAEMON
269 // write to Listcontrol
270 if (toGUI) {
271 theApp->AddGuiLogLine(line);
272 }
273#endif
274}
275
276
277void CLogger::EmergencyLog(const wxString &message, bool closeLog)
278{
279 fprintf(stderrstderr, "%s", (const char*)unicode2char(message));
280 m_ApplogBuf += message;
281 FlushApplog();
282 if (closeLog && applog) {
283 applog->Close();
284 applog = NULL__null;
285 }
286}
287
288
289void CLogger::FlushApplog()
290{
291 if (applog) { // Wait with output until logfile is actually opened
292 wxStringInputStream stream(m_ApplogBuf);
293 (*applog) << stream;
294 applog->Sync();
295 m_ApplogBuf.Clear();
296 }
297}
298
299CLogger theLogger;
300
301BEGIN_EVENT_TABLE(CLogger, wxEvtHandler)const wxEventTable CLogger::sm_eventTable = { &wxEvtHandler
::sm_eventTable, &CLogger::sm_eventTableEntries[0] }; const
wxEventTable *CLogger::GetEventTable() const { return &CLogger
::sm_eventTable; } wxEventHashTable CLogger::sm_eventHashTable
(CLogger::sm_eventTable); wxEventHashTable &CLogger::GetEventHashTable
() const { return CLogger::sm_eventHashTable; } const wxEventTableEntry
CLogger::sm_eventTableEntries[] = {
302 EVT_MULE_LOGGING(CLogger::OnLoggingEvent)wxEventTableEntry(MULE_EVT_LOGLINE, -1, -1, wxNewEventTableFunctor
(MULE_EVT_LOGLINE, (wxObjectEventFunction) (wxEventFunction) static_cast
<MuleLogEventFunction>(&CLogger::OnLoggingEvent)), (
wxObject*) __null),
303END_EVENT_TABLE()wxEventTableEntry(wxEVT_NULL, 0, 0, __null, __null) };
304
305
306CLoggerTarget::CLoggerTarget()
307{
308}
309
310void CLoggerTarget::DoLogText(const wxString &msg)
311{
312 // prevent infinite recursion
313 static bool recursion = false;
314 if (recursion) {
315 return;
316 }
317 recursion = true;
318
319 // This is much simpler than manually handling all wx log-types.
320 if (msg.StartsWith(_("ERROR: ")wxGetTranslation(("ERROR: "))) || msg.StartsWith(_("WARNING: ")wxGetTranslation(("WARNING: ")))) {
321 AddLogLineC(msg)theLogger.AddLogLine(L"Logger.cpp", 321, true, logStandard, msg
)
;
322 } else {
323 AddLogLineN(msg)theLogger.AddLogLine(L"Logger.cpp", 323, false, logStandard, msg
)
;
324 }
325
326 recursion = false;
327}
328
329CLoggerAccess::CLoggerAccess()
330{
331 m_bufferlen = 4096;
332 m_buffer = new wxCharBuffer(m_bufferlen);
333 m_logfile = NULL__null;
334 Reset();
335}
336
337
338void CLoggerAccess::Reset()
339{
340 delete m_logfile;
341 m_logfile = new wxFFileInputStream(theLogger.GetLogfileName());
342 m_pos = 0;
343 m_ready = false;
344}
345
346
347CLoggerAccess::~CLoggerAccess()
348{
349 delete m_buffer;
350 delete m_logfile;
351}
352
353
354//
355// read a line of text from the logfile if available
356// (can't believe there's no library function for this >:( )
357//
358bool CLoggerAccess::HasString()
359{
360 while (!m_ready) {
361 int c = m_logfile->GetC();
362 if (c == wxEOF) {
363 break;
364 }
365 // check for buffer overrun
366 if (m_pos == m_bufferlen) {
367 m_bufferlen += 1024;
368 m_buffer->extend(m_bufferlen);
369 }
370 m_buffer->data()[m_pos++] = c;
371 if (c == '\n') {
372 if (m_buffer->data()[0] == '.') {
373 // Log-only line, skip
374 m_pos = 0;
375 } else {
376 m_ready = true;
377 }
378 }
379 }
380 return m_ready;
381}
382
383
384bool CLoggerAccess::GetString(wxString & s)
385{
386 if (!HasString()) {
387 return false;
388 }
389 s = wxString(m_buffer->data(), wxConvUTF8wxGet_wxConvUTF8(), m_pos);
390 m_pos = 0;
391 m_ready = false;
392 return true;
393}
394
395// Functions for EC logging
396
397#ifdef __DEBUG__
398#include "ec/cpp/ECLog.h"
399
400bool ECLogIsEnabled()
401{
402 return theLogger.IsEnabled(logEC);
403}
404
405void DoECLogLine(const wxString &line)
406{
407 // without file/line
408 theLogger.AddLogLine(wxEmptyString, 0, false, logStandard, line, false, false);
409}
410
411#endif /* __DEBUG__ */
412// File_checked_for_headers