--- a/mcabber/src/hbuf.c Sun Nov 11 18:49:43 2007 +0100
+++ b/mcabber/src/hbuf.c Sun Nov 11 23:13:35 2007 +0100
@@ -123,18 +123,26 @@
{
GList *curr_elt;
char *line;
+ guint hbb_blocksize, textlen;
hbuf_block *hbuf_block_elt;
if (!text) return;
+ textlen = strlen(text);
+ hbb_blocksize = MAX(textlen+1, HBB_BLOCKSIZE);
+
hbuf_block_elt = g_new0(hbuf_block, 1);
hbuf_block_elt->prefix.timestamp = timestamp;
hbuf_block_elt->prefix.flags = prefix_flags;
hbuf_block_elt->prefix.mucnicklen = mucnicklen;
if (!*p_hbuf) {
- hbuf_block_elt->ptr = g_new(char, HBB_BLOCKSIZE);
+ hbuf_block_elt->ptr = g_new(char, hbb_blocksize);
+ if (!hbuf_block_elt->ptr) {
+ g_free(hbuf_block_elt);
+ return;
+ }
hbuf_block_elt->flags = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
- hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
+ hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
} else {
hbuf_block *hbuf_b_prev;
// Set p_hbuf to the end of the list, to speed up history loading
@@ -147,17 +155,15 @@
}
*p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
- if (strlen(text) >= HBB_BLOCKSIZE) {
- // Too long
- text = "[ERR:LINE_TOO_LONG]";
- hbuf_block_elt->prefix.flags |= HBB_PREFIX_INFO;
- }
-
- if (hbuf_block_elt->ptr + strlen(text) >= hbuf_block_elt->ptr_end_alloc) {
+ if (hbuf_block_elt->ptr + textlen >= hbuf_block_elt->ptr_end_alloc) {
// Too long for the current allocated bloc, we need another one
- if (!maxhbufblocks) {
+ if (!maxhbufblocks || textlen >= HBB_BLOCKSIZE) {
// No limit, let's allocate a new block
- hbuf_block_elt->ptr = g_new0(char, HBB_BLOCKSIZE);
+ // If the message text is big, we won't bother to reuse an old block
+ // as well (it could be too small and cause a segfault).
+ hbuf_block_elt->ptr = g_new0(char, hbb_blocksize);
+ hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
+ // XXX We should check the return value.
} else {
GList *hbuf_head, *hbuf_elt;
hbuf_block *hbuf_b_elt;
@@ -174,10 +180,12 @@
}
// If we can't allocate a new area, reuse the previous block(s)
if (n < maxhbufblocks) {
- hbuf_block_elt->ptr = g_new0(char, HBB_BLOCKSIZE);
+ hbuf_block_elt->ptr = g_new0(char, hbb_blocksize);
+ hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
} else {
// Let's use an old block, and free the extra blocks if needed
char *allocated_block = NULL;
+ char *end_of_allocated_block = NULL;
while (n >= maxhbufblocks) {
int start_of_block = 1;
for (hbuf_elt = hbuf_head; hbuf_elt; hbuf_elt = hbuf_head) {
@@ -185,28 +193,30 @@
if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) {
if (start_of_block-- == 0)
break;
- if (n == maxhbufblocks)
+ if (n == maxhbufblocks) {
allocated_block = hbuf_b_elt->ptr;
- else
+ end_of_allocated_block = hbuf_b_elt->ptr_end_alloc;
+ } else {
g_free(hbuf_b_elt->ptr);
+ }
}
g_free(hbuf_b_elt);
hbuf_head = *p_hbuf = g_list_delete_link(hbuf_head, hbuf_elt);
}
n--;
}
- memset(allocated_block, 0, HBB_BLOCKSIZE);
+ memset(allocated_block, 0, end_of_allocated_block-allocated_block);
hbuf_block_elt->ptr = allocated_block;
+ hbuf_block_elt->ptr_end_alloc = end_of_allocated_block;
}
}
hbuf_block_elt->flags = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
- hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
}
line = hbuf_block_elt->ptr;
// Ok, now we can copy the text..
strcpy(line, text);
- hbuf_block_elt->ptr_end = line + strlen(line) + 1;
+ hbuf_block_elt->ptr_end = line + textlen + 1;
curr_elt = g_list_last(*p_hbuf);