struct MsgCounts msgBufCounts = { 0, 0 };
struct MsgCounts msgCounts = { 0, 0 };
+/* XXX HACK HACK HACK XXX */
+#if 1
+/* First, force assertion checking */
+#undef NDEBUG
+#include <assert.h>
+
+/* This routine is TEMPORARY and is intended to track down a problem we're
+ * having with apparent buffer overflows in this file.
+ */
+static void
+msgq_integrity(void)
+{
+ struct MsgBuf *mb;
+ struct Msg *msg;
+
+ for (mb = MQData.msgs; mb; mb = mb->next)
+ assert(((unsigned long)mb) != 0x8000a0d);
+ for (mb = MQData.free_mbs; mb; mb = mb->next)
+ assert(((unsigned long)mb) != 0x8000a0d);
+ for (msg = MQData.free_msgs; msg; msg = msg->next)
+ assert(((unsigned long)msg) != 0x8000a0d);
+}
+#else
+#define msgq_integrity() ((void)0)
+#endif /* XXX HACK HACK HACK XXX */
+
/*
* This routine is used to remove a certain amount of data from a given
* queue and release the Msg (and MsgBuf) structure if needed
struct Msg *m;
unsigned int msglen;
+ msgq_integrity();
+
assert(0 != mq);
assert(0 != qlist);
assert(0 != qlist->head);
m->sent += *length_p; /* this much of the message has been sent */
*length_p = 0; /* we've dealt with it all */
}
+
+ msgq_integrity();
}
/*
void
msgq_init(struct MsgQ *mq)
{
+ msgq_integrity();
+
assert(0 != mq);
mq->length = 0;
mq->queue.tail = 0;
mq->prio.head = 0;
mq->prio.tail = 0;
+
+ msgq_integrity();
}
/*
void
msgq_delete(struct MsgQ *mq, unsigned int length)
{
+ msgq_integrity();
+
assert(0 != mq);
while (length > 0) {
else
break;
}
-}
-
-/*
- * This is similiar to the dbuf_map() function to allow us to plug it
- * into the existing code more easily; we may want to have something
- * more fancy in the future that would allow us to make some intelligent
- * use of writev or similiar functions.
- */
-const char *
-msgq_map(const struct MsgQ *mq, unsigned int *length_p)
-{
- assert(0 != mq);
- assert(0 != length_p);
- if (mq->length <= 0)
- return 0;
-
- if (mq->queue.head && mq->queue.head->sent > 0) { /* partial msg on norm q */
- *length_p = mq->queue.head->msg->length - mq->queue.head->sent;
- return mq->queue.head->msg->msg + mq->queue.head->sent;
- } else if (mq->prio.head) { /* message (partial or complete) on prio queue */
- *length_p = mq->prio.head->msg->length - mq->prio.head->sent;
- return mq->prio.head->msg->msg + mq->prio.head->sent;
- } else if (mq->queue.head) { /* message on normal queue */
- *length_p = mq->queue.head->msg->length; /* partial already dealt with */
- return mq->queue.head->msg->msg;
- }
-
- return 0; /* shouldn't ever happen */
+ msgq_integrity();
}
/*
struct Msg *prio;
int i = 0;
+ msgq_integrity();
+
assert(0 != mq);
assert(0 != iov);
assert(0 != count);
assert(0 != len);
- if (mq->length <= 0) /* no data to map */
+ if (mq->length <= 0) { /* no data to map */
+ msgq_integrity();
return 0;
+ }
if (mq->queue.head && mq->queue.head->sent > 0) { /* partial msg on norm q */
iov[i].iov_base = mq->queue.head->msg->msg + mq->queue.head->sent;
queue = mq->queue.head->next; /* where we start later... */
i++; /* filled an iovec... */
- if (!--count) /* check for space */
+ if (!--count) { /* check for space */
+ msgq_integrity();
return i;
+ }
} else
queue = mq->queue.head; /* start at head of queue */
prio = mq->prio.head->next; /* where we start later... */
i++; /* filled an iovec... */
- if (!--count) /* check for space */
+ if (!--count) { /* check for space */
+ msgq_integrity();
return i;
+ }
} else
prio = mq->prio.head; /* start at head of prio */
*len += iov[i].iov_len;
i++; /* filled an iovec... */
- if (!--count) /* check for space */
+ if (!--count) { /* check for space */
+ msgq_integrity();
return i;
+ }
}
for (; queue; queue = queue->next) { /* go through normal queue */
*len += iov[i].iov_len;
i++; /* filled an iovec... */
- if (!--count) /* check for space */
+ if (!--count) { /* check for space */
+ msgq_integrity();
return i;
+ }
}
+ msgq_integrity();
+
return i;
}
{
struct MsgBuf *mb;
+ msgq_integrity();
+
assert(0 != format);
if (!(mb = MQData.free_mbs)) { /* do I need to allocate one? */
mb->ref = 1;
/* fill the buffer */
- mb->length = ircd_vsnprintf(dest, mb->msg, sizeof(mb->msg) - 2, format, vl);
+ mb->length = ircd_vsnprintf(dest, mb->msg, sizeof(mb->msg) - 3, format, vl);
mb->msg[mb->length++] = '\r'; /* add \r\n to buffer */
mb->msg[mb->length++] = '\n';
mb->msg[mb->length] = '\0'; /* not strictly necessary */
+ assert(mb->length < sizeof(mb->msg));
+
if (MQData.msgs) /* link it into the list */
MQData.msgs->prev_p = &mb->next;
MQData.msgs = mb;
+ msgq_integrity();
+
return mb;
}
{
va_list vl;
+ msgq_integrity();
+
assert(0 != mb);
assert(0 != format);
+ assert(2 < mb->length);
+ assert(sizeof(mb->msg) > mb->length);
+
mb->length -= 2; /* back up to before \r\n */
va_start(vl, format); /* append to the buffer */
mb->length += ircd_vsnprintf(dest, mb->msg + mb->length,
- sizeof(mb->msg) - 2 - mb->length, format, vl);
+ sizeof(mb->msg) - 3 - mb->length, format, vl);
va_end(vl);
mb->msg[mb->length++] = '\r'; /* add \r\n to buffer */
mb->msg[mb->length++] = '\n';
mb->msg[mb->length] = '\0'; /* not strictly necessary */
+
+ assert(mb->length < sizeof(mb->msg));
+
+ msgq_integrity();
}
/*
void
msgq_clean(struct MsgBuf *mb)
{
+ msgq_integrity();
+
assert(0 != mb);
assert(0 < mb->ref);
assert(0 != mb->prev_p);
msgBufCounts.used--; /* decrement the usage count */
}
+
+ msgq_integrity();
}
/*
struct MsgQList *qlist;
struct Msg *msg;
+ msgq_integrity();
+
assert(0 != mq);
assert(0 != mb);
assert(0 < mb->ref);
mq->length += mb->length; /* update the queue length */
mq->count++; /* and the queue count */
+
+ msgq_integrity();
}
/*
msgq_count_memory(size_t *msg_alloc, size_t *msg_used, size_t *msgbuf_alloc,
size_t *msgbuf_used)
{
+ msgq_integrity();
+
assert(0 != msg_alloc);
assert(0 != msg_used);
assert(0 != msgbuf_alloc);
*msg_used = msgCounts.used * sizeof(struct Msg);
*msgbuf_alloc = msgCounts.alloc * sizeof(struct MsgBuf);
*msgbuf_used = msgCounts.used * sizeof(struct MsgBuf);
+
+ msgq_integrity();
}
/*
{
assert(0 != mb);
- return sizeof(mb->msg) - mb->length; /* the -2 for \r\n is in mb->length */
+ return sizeof(mb->msg) - mb->length - 1; /* \r\n counted in mb->length */
}