Bug Summary

File:rootdir/src/UserEvents.cpp
Warning:line 94, column 9
Access of 's_EventList' at an overflowing index, while it holds only 4 'struct (unnamed at UserEvents.cpp:40:8)' 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 UserEvents.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++ UserEvents.cpp
1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2006-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
26#include "UserEvents.h"
27
28
29#include <common/Format.h>
30#include "Logger.h"
31#include "Preferences.h"
32#include "PartFile.h"
33#include "TerminationProcess.h" // Needed for CTerminationProcess
34
35
36#include <wx/process.h>
37
38
39#define USEREVENTS_EVENT(ID, NAME, VARS)case CUserEvents::ID: { VARS break; } { wxT(#ID)L#ID, NAME, false, wxEmptyString, false, wxEmptyString },
40static struct {
41 const wxString key;
42 const wxString name;
43 bool core_enabled;
44 wxString core_command;
45 bool gui_enabled;
46 wxString gui_command;
47} s_EventList[] = {
48 USEREVENTS_EVENTLIST()case CUserEvents::DownloadCompleted: { command.Replace(L"%" L"FILE"
, static_cast<const CPartFile*>(object)->GetFullName
().GetRaw()); command.Replace(L"%" L"NAME", static_cast<const
CPartFile*>(object)->GetFileName().GetRaw()); command.
Replace(L"%" L"HASH", static_cast<const CPartFile*>(object
)->GetFileHash().Encode()); command.Replace(L"%" L"SIZE", (
CFormat(L"%llu") % static_cast<const CPartFile*>(object
)->GetFileSize()).GetString()); command.Replace(L"%" L"DLACTIVETIME"
, CastSecondsToHM(static_cast<const CPartFile*>(object)
->GetDlActiveTime())); break; } case CUserEvents::NewChatSession
: { command.Replace(L"%" L"SENDER", *static_cast<const wxString
*>(object)); break; } case CUserEvents::OutOfDiskSpace: { command
.Replace(L"%" L"PARTITION", wxString(static_cast<const wxChar
*>(object))); break; } case CUserEvents::ErrorOnCompletion
: { command.Replace(L"%" L"FILE", static_cast<const CPartFile
*>(object)->GetFullName().GetRaw()); break; }
49 /* This macro expands to initialise the list of user event types. Example:
50 { wxT("NewChatSession"), wxTRANSLATE("New chat session started"), false, wxEmptyString, false, wxEmptyString }, */
51};
52#undef USEREVENTS_EVENT
53
54
55#ifdef __WXDEBUG__
56inline bool CheckIndex(const unsigned int idx)
57{
58 return (idx < itemsof(s_EventList)(sizeof(s_EventList) / sizeof(s_EventList[0])));
59}
60#endif
61
62unsigned int CUserEvents::GetCount()
63{
64 return itemsof(s_EventList)(sizeof(s_EventList) / sizeof(s_EventList[0]));
65}
66
67const wxString& CUserEvents::GetDisplayName(enum EventType event)
68{
69 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 69, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
70 return s_EventList[event].name;
71}
72
73bool CUserEvents::IsCoreCommandEnabled(enum EventType event)
74{
75 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 75, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
76 return s_EventList[event].core_enabled;
77}
78
79bool CUserEvents::IsGUICommandEnabled(enum EventType event)
80{
81 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 81, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
82 return s_EventList[event].gui_enabled;
83}
84
85const wxString& CUserEvents::GetKey(const unsigned int event)
86{
87 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 87, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
88 return s_EventList[event].key;
89}
90
91bool& CUserEvents::GetCoreEnableVar(const unsigned int event)
92{
93 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 93, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
1
Taking false branch
2
Assuming 'wxTheAssertHandler' is null
3
Loop condition is false. Exiting loop
94 return s_EventList[event].core_enabled;
4
Access of 's_EventList' at an overflowing index, while it holds only 4 'struct (unnamed at UserEvents.cpp:40:8)' elements
95}
96
97wxString& CUserEvents::GetCoreCommandVar(const unsigned int event)
98{
99 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 99, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
100 return s_EventList[event].core_command;
101}
102
103bool& CUserEvents::GetGUIEnableVar(const unsigned int event)
104{
105 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 105, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
106 return s_EventList[event].gui_enabled;
107}
108
109wxString& CUserEvents::GetGUICommandVar(const unsigned int event)
110{
111 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 111, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
112 return s_EventList[event].gui_command;
113}
114
115#define USEREVENTS_EVENT(ID, NAME, VARS)case CUserEvents::ID: { VARS break; } case CUserEvents::ID: { VARS break; }
116#define USEREVENTS_REPLACE_VAR(VAR, DESC, CODE)command.Replace(L"%" VAR, CODE); command.Replace(wxT("%")L"%" VAR, CODE);
117static void ExecuteCommand(
118 enum CUserEvents::EventType event,
119 const void* object,
120 const wxString& cmd)
121{
122 // This variable is needed by the USEREVENTS_EVENTLIST macro.
123 wxString command = cmd;
124 switch (event) {
125 USEREVENTS_EVENTLIST()case CUserEvents::DownloadCompleted: { command.Replace(L"%" L"FILE"
, static_cast<const CPartFile*>(object)->GetFullName
().GetRaw()); command.Replace(L"%" L"NAME", static_cast<const
CPartFile*>(object)->GetFileName().GetRaw()); command.
Replace(L"%" L"HASH", static_cast<const CPartFile*>(object
)->GetFileHash().Encode()); command.Replace(L"%" L"SIZE", (
CFormat(L"%llu") % static_cast<const CPartFile*>(object
)->GetFileSize()).GetString()); command.Replace(L"%" L"DLACTIVETIME"
, CastSecondsToHM(static_cast<const CPartFile*>(object)
->GetDlActiveTime())); break; } case CUserEvents::NewChatSession
: { command.Replace(L"%" L"SENDER", *static_cast<const wxString
*>(object)); break; } case CUserEvents::OutOfDiskSpace: { command
.Replace(L"%" L"PARTITION", wxString(static_cast<const wxChar
*>(object))); break; } case CUserEvents::ErrorOnCompletion
: { command.Replace(L"%" L"FILE", static_cast<const CPartFile
*>(object)->GetFullName().GetRaw()); break; }
126 /* This macro expands to handle all user event types. Example:
127 case CUserEvents::NewChatSession: {
128 command.Replace( wxT("%SENDER"), *((wxString*)object) );
129 break;
130 } */
131 }
132 if (!command.empty()) {
133 CTerminationProcess *p = new CTerminationProcess(cmd);
134 if (!wxExecute(command, wxEXEC_ASYNC, p)) {
135 // If wxExecute fails, we need to delete the CTerminationProcess
136 // otherwise it will leak.
137 delete p;
138 AddLogLineC(CFormat(_("Failed to execute command `%s' on `%s' event.")) %theLogger.AddLogLine(L"UserEvents.cpp", 139, true, logStandard
, CFormat(wxGetTranslation(("Failed to execute command `%s' on `%s' event."
))) % command % s_EventList[event].name)
139 command % s_EventList[event].name)theLogger.AddLogLine(L"UserEvents.cpp", 139, true, logStandard
, CFormat(wxGetTranslation(("Failed to execute command `%s' on `%s' event."
))) % command % s_EventList[event].name)
;
140 }
141 }
142}
143
144void CUserEvents::ProcessEvent(enum EventType event, const void* object)
145{
146 wxASSERT(CheckIndex(event))do { if ( CheckIndex(event) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 146, __FUNCTION__, "CheckIndex(event)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
147 wxASSERT(object != NULL)do { if ( object != __null ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("UserEvents.cpp", 147, __FUNCTION__, "object != __null"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
148
149#ifndef CLIENT_GUI
150 if (s_EventList[event].core_enabled) {
151 ExecuteCommand(event, object, s_EventList[event].core_command);
152 }
153#endif
154#ifndef AMULE_DAEMON
155 if (s_EventList[event].gui_enabled) {
156 ExecuteCommand(event, object, s_EventList[event].gui_command);
157 }
158#endif
159}