--- Begin Message ---
Package: ircd
Version: 2.10.07-1.1
Severity: important
-- System Information
Debian Release: 3.0
Kernel Version: Linux SofaSurfer 2.4.19-pre4-ben0 #27 Sun Mar 24 11:52:37 CET
2002 ppc unknown
Versions of the packages ircd depends on:
ii adduser 3.47 Add and remove users and groups
ii libc6 2.2.5-4 GNU C Library: Shared libraries and Timezone
--- Ignoring conffile /etc/ircd/ircd.conf (not world readable)
--- Problem description and investigation
Started ircd (preferably with -t -x 10 to get some information about
program status). Connected 2 irc clients to this server. Join/create a
channel with one client. Then, as soon as the second client joins the
same channel, ircd segfaults.
After quite some debugging I came to the conclusion that the reason for
this is the way stdarg is used. va_start and va_end are not placed as
the stdarg man-page says:
"Multiple transversals of the list, each bracketed by va_start and
va_end are possible."
-- Solution
On several occasions in the source, this is not done correctly it seems,
i. e. there are iterations with calls that use the va_list as parameters
and don't use va_end after each call and va_start before. Instead only
one call to va_start and va_end respectively around several references
to vl as function parameter can happen. I have modified the source to
add calls to va_start and va_end as the man-page suggests, recompiled it
and did almost half an hour of testing with 3 clients without ircd
segfaulting again.
Here's the resulting patch which should not interfere with ircd running
on archs that aren't as picky about varargs as powerpc ;)
==== START ====
diff -Naur ircd-2.10.07/ircd/s_serv.c ircd-2.10.07-tl1/ircd/s_serv.c
--- ircd-2.10.07/ircd/s_serv.c Sat Dec 18 02:19:38 1999
+++ ircd-2.10.07-tl1/ircd/s_serv.c Mon Apr 8 23:59:49 2002
@@ -73,7 +73,12 @@
(char *)RunMalloc(strlen(me.name) + strlen(host) + 22 + strlen(fmt));
va_start(vl, fmt);
if (!IsServer(sptr))
- return vexit_client_msg(cptr, cptr, &me, fmt, vl);
+ {
+ int ret;
+ ret = vexit_client_msg(cptr, cptr, &me, fmt, vl);
+ va_end(vl);
+ return ret;
+ }
sprintf_irc(buf, ":%s SQUIT %s " TIME_T_FMT " :", me.name, host, timestamp);
strcat(buf, fmt);
vsendto_one(cptr, buf, vl);
diff -Naur ircd-2.10.07/ircd/send.c ircd-2.10.07-tl1/ircd/send.c
--- ircd-2.10.07/ircd/send.c Sat Dec 18 02:19:39 1999
+++ ircd-2.10.07-tl1/ircd/send.c Mon Apr 8 23:56:59 2002
@@ -344,7 +344,6 @@
Reg2 aClient *acptr;
Reg3 int i;
- va_start(vl, pattern);
++sentalong_marker;
for (lp = chptr->members; lp; lp = lp->next)
@@ -354,17 +353,24 @@
(lp->flags & CHFL_ZOMBIE) || IsDeaf(acptr))
continue;
if (MyConnect(acptr)) /* (It is always a client) */
+ {
+ va_start(vl, pattern);
vsendto_prefix_one(acptr, from, pattern, vl);
+ va_end(vl);
+ }
else if (sentalong[(i = acptr->from->fd)] != sentalong_marker)
{
sentalong[i] = sentalong_marker;
/* Don't send channel messages to links that are still eating
the net.burst: -- Run 2/1/1997 */
if (!IsBurstOrBurstAck(acptr->from))
+ {
+ va_start(vl, pattern);
vsendto_prefix_one(acptr, from, pattern, vl);
+ va_end(vl);
+ }
}
}
- va_end(vl);
return;
}
@@ -375,7 +381,6 @@
Reg1 Link *lp;
Reg2 aClient *acptr;
- va_start(vl, pattern);
for (lp = chptr->members; lp; lp = lp->next)
{
@@ -385,9 +390,12 @@
(lp->flags & CHFL_ZOMBIE) || IsDeaf(acptr))
continue;
if (MyConnect(acptr)) /* (It is always a client) */
+ {
+ va_start(vl, pattern);
vsendto_prefix_one(acptr, from, pattern, vl);
+ va_end(vl);
+ }
}
- va_end(vl);
return;
}
@@ -403,8 +411,6 @@
char *source, *tp, *msg;
#endif
- va_start(vl, pattern);
-
++sentalong_marker;
for (lp = chptr->members; lp; lp = lp->next)
{
@@ -423,11 +429,17 @@
/* Don't send channel messages to links that are
still eating the net.burst: -- Run 2/1/1997 */
if (!IsBurstOrBurstAck(acptr->from))
+ {
+ va_start(vl, pattern);
vsendto_prefix_one(acptr, from, pattern, vl);
+ va_end(vl);
+ }
}
}
#ifndef NO_PROTOCOL9
+ va_start(vl, pattern);
+
/* Send message to all 2.9 servers */
/* This is a hack, because it assumes that we know how `vl' is build up */
source = va_arg(vl, char *);
@@ -480,9 +492,9 @@
}
}
}
+ va_end(vl);
#endif
- va_end(vl);
return;
}
@@ -539,7 +551,6 @@
Reg1 Link *chan;
Reg2 Link *member;
- va_start(vl, pattern);
++sentalong_marker;
if (acptr->fd >= 0)
@@ -553,12 +564,17 @@
if (MyConnect(cptr) && sentalong[cptr->fd] != sentalong_marker)
{
sentalong[cptr->fd] = sentalong_marker;
+ va_start(vl, pattern);
vsendto_prefix_one(cptr, acptr, pattern, vl);
+ va_end(vl);
}
}
if (MyConnect(acptr))
+ {
+ va_start(vl, pattern);
vsendto_prefix_one(acptr, acptr, pattern, vl);
- va_end(vl);
+ va_end(vl);
+ }
return;
}
@@ -574,10 +590,15 @@
Reg1 Link *lp;
Reg2 aClient *acptr;
- for (va_start(vl, pattern), lp = chptr->members; lp; lp = lp->next)
+ for (lp = chptr->members; lp; lp = lp->next)
+ {
if (MyConnect(acptr = lp->value.cptr) && !(lp->flags & CHFL_ZOMBIE))
+ {
+ va_start(vl, pattern);
vsendto_prefix_one(acptr, from, pattern, vl);
- va_end(vl);
+ va_end(vl);
+ }
+ }
return;
}
@@ -613,7 +634,6 @@
Reg1 int i;
Reg2 aClient *cptr, *acptr;
- va_start(vl, pattern);
for (i = 0; i <= highest_fd; i++)
{
if (!(cptr = loc_clients[i]))
@@ -635,9 +655,10 @@
/* my client, does he match ? */
else if (!(IsUser(cptr) && match_it(cptr, mask, what)))
continue;
+ va_start(vl, pattern);
vsendto_prefix_one(cptr, from, pattern, vl);
+ va_end(vl);
}
- va_end(vl);
return;
}
@@ -778,7 +799,6 @@
Reg1 int i;
Reg2 aClient *cptr;
- va_start(vl, pattern);
++sentalong_marker;
for (cptr = client; cptr; cptr = cptr->next)
{
@@ -790,9 +810,10 @@
if (cptr->from == one)
continue; /* ...was the one I should skip */
sentalong[i] = sentalong_marker;
+ va_start(vl, pattern);
vsendto_prefix_one(cptr->from, from, pattern, vl);
+ va_end(vl);
}
- va_end(vl);
return;
}
@@ -813,6 +834,7 @@
va_start(vl, pattern);
++sentalong_marker;
vsprintf_irc(sendbuf, pattern, vl);
+ va_end(vl);
for (cptr = client; cptr; cptr = cptr->next)
{
if (!SendDebug(cptr))
@@ -827,7 +849,6 @@
continue;
sendbufto_one(cptr);
}
- va_end(vl);
return;
}
@@ -872,11 +893,15 @@
{
va_list vl;
Dlink *lp;
- va_start(vl, pattern);
for (lp = me.serv->down; lp; lp = lp->next)
+ {
if (lp->value.cptr != cptr && Protocol(lp->value.cptr) <= p)
+ {
+ va_start(vl, pattern);
vsendto_one(lp->value.cptr, pattern, vl);
- va_end(vl);
+ va_end(vl);
+ }
+ }
}
/*
@@ -886,9 +911,13 @@
{
va_list vl;
Dlink *lp;
- va_start(vl, pattern);
for (lp = me.serv->down; lp; lp = lp->next)
+ {
if (lp->value.cptr != cptr && Protocol(lp->value.cptr) >= p)
+ {
+ va_start(vl, pattern);
vsendto_one(lp->value.cptr, pattern, vl);
- va_end(vl);
+ va_end(vl);
+ }
+ }
}
diff -Naur ircd-2.10.07/ircd/sprintf_irc.c ircd-2.10.07-tl1/ircd/sprintf_irc.c
--- ircd-2.10.07/ircd/sprintf_irc.c Tue Jul 21 04:41:06 1998
+++ ircd-2.10.07-tl1/ircd/sprintf_irc.c Mon Apr 8 21:53:01 2002
@@ -288,6 +288,7 @@
if (c == 's')
{
register const char *p1 = va_arg(vl, const char *);
+
if ((*str = *p1))
while ((*++str = *++p1));
continue;
diff -Naur ircd-2.10.07/ircd/stamp-m ircd-2.10.07-tl1/ircd/stamp-m
--- ircd-2.10.07/ircd/stamp-m Thu Jan 1 01:00:00 1970
+++ ircd-2.10.07-tl1/ircd/stamp-m Mon Apr 8 20:58:52 2002
@@ -0,0 +1 @@
+timestamp
diff -Naur ircd-2.10.07/ircd/support.c ircd-2.10.07-tl1/ircd/support.c
--- ircd-2.10.07/ircd/support.c Mon Jul 12 12:14:51 1999
+++ ircd-2.10.07-tl1/ircd/support.c Tue Apr 9 00:01:46 2002
@@ -202,6 +202,8 @@
Debug((DEBUG_FATAL, "Dumped core : core.%d", p));
sendto_ops("Dumped core : core.%d", p);
vdebug(DEBUG_FATAL, pattern, vl);
+ va_end(vl);
+ va_start(vl, pattern);
vsendto_ops(pattern, vl);
#ifdef __cplusplus
s_die(0);
==== END ====
--- End Message ---