Hi,
I found some crashes caused by missing NULL pointer checks.
I fixed most of them and added additional checks.
The common crash was while receiving a pager message from a non existant
user (mostly spambots) here:
---
ICQUser *u = gUserManager.FetchUser(nUin, LOCK_R);
bool bIgnore = u->IgnoreList();
gUserManager.DropUser(u);
---
u was NULL very often and I think you can see what happens then ;-)
I provided a patch for that.
(I hope googlegroups accept the attached patch ;-) )
See Ya
FloSoft
diff -urN licq-1.3.4/src/icqd-srv.cpp licq-1.3.4-fixed/src/icqd-srv.cpp
--- licq-1.3.4/src/icqd-srv.cpp 2006-10-15 14:10:58.000000000 +0200
+++ licq-1.3.4-fixed/src/icqd-srv.cpp 2007-08-28 11:59:20.000000000 +0200
@@ -144,7 +144,7 @@
{
// If they aren't a current server user and not in the ingore list,
// let's import them!
- if (pUser->GetSID() == 0 && !pUser->IgnoreList())
+ if (pUser && pUser->GetSID() == 0 && !pUser->IgnoreList())
{
UserStringList::const_iterator p = std::find(doneUsers.begin(),
doneUsers.end(),
pUser->IdString());
@@ -177,7 +177,7 @@
UserStringList visibleUsers, invisibleUsers, ignoredUsers;
FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_R)
{
- if (pUser->IgnoreList() && pUser->GetSID() == 0)
+ if (pUser && pUser->IgnoreList() && pUser->GetSID() == 0)
{
ignoredUsers.push_back(strdup(pUser->IdString()));
pthread_mutex_lock(&mutex_modifyserverusers);
@@ -186,7 +186,7 @@
}
else
{
- if (pUser->InvisibleList() && pUser->GetInvisibleSID() == 0)
+ if (pUser && pUser->InvisibleList() && pUser->GetInvisibleSID() == 0)
{
invisibleUsers.push_back(strdup(pUser->IdString()));
pthread_mutex_lock(&mutex_modifyserverusers);
@@ -194,7 +194,7 @@
pthread_mutex_unlock(&mutex_modifyserverusers);
}
- if (pUser->VisibleList() && pUser->GetVisibleSID() == 0)
+ if (pUser && pUser->VisibleList() && pUser->GetVisibleSID() == 0)
{
visibleUsers.push_back(strdup(pUser->IdString()));
pthread_mutex_lock(&mutex_modifyserverusers);
@@ -1219,6 +1219,7 @@
UserStringList users;
FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_W)
{
+ assert(pUser);
n++;
users.push_back(strdup(pUser->IdString()));
if (n == m_nMaxUsersPerPacket)
@@ -1266,7 +1267,7 @@
UserStringList users;
FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_R)
{
- if (pUser->GetInGroup(GROUPS_SYSTEM, GROUP_VISIBLE_LIST) )
+ if (pUser && pUser->GetInGroup(GROUPS_SYSTEM, GROUP_VISIBLE_LIST) )
users.push_back(strdup(pUser->IdString()));
}
FOR_EACH_PROTO_USER_END
@@ -1282,7 +1283,7 @@
UserStringList users;
FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_R)
{
- if (pUser->GetInGroup(GROUPS_SYSTEM, GROUP_INVISIBLE_LIST) )
+ if (pUser && pUser->GetInGroup(GROUPS_SYSTEM, GROUP_INVISIBLE_LIST) )
users.push_back(strdup(pUser->IdString()));
}
FOR_EACH_PROTO_USER_END
@@ -1580,6 +1581,7 @@
// Delete all the users in groups
FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_W)
{
+ assert(pUser);
n++;
users.push_back(strdup(pUser->IdString()));
if (n == m_nMaxUsersPerPacket)
@@ -1610,7 +1612,7 @@
FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_W)
{
- if (pUser->GetInvisibleSID())
+ if (pUser && pUser->GetInvisibleSID())
{
n++;
users.push_back(strdup(pUser->IdString()));
@@ -1643,7 +1645,7 @@
FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_W)
{
- if (pUser->GetVisibleSID())
+ if (pUser && pUser->GetVisibleSID())
{
n++;
users.push_back(strdup(pUser->IdString()));
@@ -2008,7 +2010,7 @@
// online field
FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_W)
{
- if (!pUser->StatusOffline())
+ if (pUser && !pUser->StatusOffline())
ChangeUserStatus(pUser, ICQ_STATUS_OFFLINE);
}
FOR_EACH_PROTO_USER_END
@@ -2182,6 +2184,7 @@
FOR_EACH_USER_START(LOCK_R)
{
+ assert(pUser);
ParseDigits(szParsedNumber1, pUser->GetCellularNumber(), 15);
ParseDigits(szParsedNumber2, szCellular, 15);
if (!strcmp(szParsedNumber1, szParsedNumber2))
@@ -4919,9 +4922,14 @@
case ICQ_CMDxSUB_EMAILxPAGER:
{
ICQUser *u = gUserManager.FetchUser(nUin, LOCK_R);
- bool bIgnore = u->IgnoreList();
- gUserManager.DropUser(u);
-
+ bool bIgnore = true;
+
+ if(u)
+ {
+ bIgnore = u->IgnoreList();
+ gUserManager.DropUser(u);
+ }
+
if (bIgnore)
{
delete eEvent; // Processing stops here, needs to be deleted
diff -urN licq-1.3.4/src/icqd-udp.cpp licq-1.3.4-fixed/src/icqd-udp.cpp
--- licq-1.3.4/src/icqd-udp.cpp 2006-10-15 14:10:58.000000000 +0200
+++ licq-1.3.4-fixed/src/icqd-udp.cpp 2007-08-28 11:44:37.000000000 +0200
@@ -302,7 +302,7 @@
UinList uins;
FOR_EACH_USER_START(LOCK_R)
{
- if (pUser->GetInGroup(GROUPS_SYSTEM, GROUP_VISIBLE_LIST) )
+ if (pUser && pUser->GetInGroup(GROUPS_SYSTEM, GROUP_VISIBLE_LIST) )
uins.push_back(pUser->Uin());
}
FOR_EACH_USER_END
@@ -320,7 +320,7 @@
UinList uins;
FOR_EACH_USER_START(LOCK_R)
{
- if (pUser->GetInGroup(GROUPS_SYSTEM, GROUP_INVISIBLE_LIST) )
+ if (pUser && pUser->GetInGroup(GROUPS_SYSTEM, GROUP_INVISIBLE_LIST) )
uins.push_back(pUser->Uin());
}
FOR_EACH_USER_END
diff -urN licq-1.3.4/src/icqpacket.cpp licq-1.3.4-fixed/src/icqpacket.cpp
--- licq-1.3.4/src/icqpacket.cpp 2006-10-15 14:10:58.000000000 +0200
+++ licq-1.3.4-fixed/src/icqpacket.cpp 2007-08-28 11:45:08.000000000 +0200
@@ -2581,7 +2581,7 @@
GroupIDList *pID = gUserManager.LockGroupIDList(LOCK_R);
for (unsigned short j = 1; j < pID->size() + 1; j++)
{
- if (u->GetInGroup(GROUPS_USER, j))
+ if (u && u->GetInGroup(GROUPS_USER, j))
{
m_nGSID = (*pID)[j-1];
if (m_nGSID)
@@ -2741,7 +2741,7 @@
// Use the first group that the user is in as the server stored group
for (unsigned short i = 1; i < pID->size() + 1; i++)
{
- if (u->GetInGroup(GROUPS_USER, i))
+ if (u && u->GetInGroup(GROUPS_USER, i))
{
m_nGSID = (*pID)[i-1];
if (m_nGSID)
diff -urN licq-1.3.4/src/user.cpp licq-1.3.4-fixed/src/user.cpp
--- licq-1.3.4/src/user.cpp 2006-10-15 14:10:58.000000000 +0200
+++ licq-1.3.4-fixed/src/user.cpp 2007-08-28 11:47:32.000000000 +0200
@@ -20,6 +20,7 @@
#include <string.h>
#include <errno.h>
#include <vector>
+#include <assert.h>
#ifdef HAVE_INET_ATON
#include <arpa/inet.h>
@@ -867,7 +868,7 @@
{
return;
}
-
+
GroupList *g = LockGroupList(LOCK_R);
// Must be called when there are no locks on GroupID and Group lists
@@ -886,6 +887,7 @@
unsigned short j;
FOR_EACH_USER_START(LOCK_W)
{
+ assert(pUser);
for (j = n; j < g->size() + 1; j++)
pUser->SetInGroup(GROUPS_USER, j, pUser->GetInGroup(GROUPS_USER, j + 1));
}
@@ -930,6 +932,8 @@
bool bInG1;
FOR_EACH_USER_START(LOCK_W)
{
+ assert(pUser);
+
bInG1 = pUser->GetInGroup(GROUPS_USER, g1);
pUser->SetInGroup(GROUPS_USER, g1, pUser->GetInGroup(GROUPS_USER, g2));
pUser->SetInGroup(GROUPS_USER, g2, bInG1);