Hello to everyone.
I have discovered a couple of bugs related to the sieve
implementation in mailutils 1.0. For the first, I include a patch that
solves it, while
for the second I have written the necessary code to expose it and I
cannot (in short time) provide a fix myself.
The first bug has to do with the vacation action implementation. In
libsieve/extensions/vacation.c file, vacation_subject() function, at
(or near) line 411 there is a check
else if (mu_message_get_header (msg, &hdr) == 0
&& mu_header_aget_value_unfold (hdr, MU_HEADER_SUBJECT, &value)
== 0)
The problem is when this check fails, when for example the message has
no subject or its subject is empty. In this case, the control goes to
if (mu_rfc2047_encode (MU_SIEVE_CHARSET, "quoted-printable",
subject, &value))
with a random subject pointer. Also the variable subject_allocated is
uninitialized. We have noticed excaustive cpu usage in our delivery
agent in our production systems because of this
(example stack trace:
#0 0xb7ea80d3 in mallopt () from /lib/tls/libc.so.6
#1 0xb7ea7f6e in mallopt () from /lib/tls/libc.so.6
#2 0xb7ea6dcb in free () from /lib/tls/libc.so.6
#3 0xb7fa7dbe in mu_header_set_value ()
#4 0xb7a4d740 in vacation_reply ()
#5 0xb7a4da38 in sieve_action_vacation ()
#6 0xb7f811fe in instr_run ()
#7 0xb7f81293 in instr_action ()
#8 0xb7f818c5 in sieve_run ()
#9 0xb7f81b88 in mu_sieve_message ()
...)
The attached patch solves the issue.
The second bug is in the sieve parser. To demonstrate the bug, I have
implemented a new sieve action called notify (attached also). This
notify action accepts a tag and has no arguments
notify [:method <url: string>]
When you have a sieve file like
#searchpath "/path/to/mailutils"
require["notify"];
if header :contains ["from"] ["kzorba"] { notify :method "sms:+3069XXXXXX"; }
everything is fine, but if you make a syntactic error and you have
#searchpath "/path/to/mailutils"
require["notify"];
if header :contains ["from"] ["kzorba"] { notify :method ; }
(the tag's argument is missing) then the sieve engine consumes all cpu
resources with the following stack trace:
(gdb) bt
#0 0xb7dd4e13 in pthread_rwlock_wrlock () from /lib/tls/libpthread.so.0
#1 0xb7fa0fc7 in monitor_pthread_wrlock (lock=0x80548d8) at monitor.c:280
#2 0xb7fa0e67 in mu_monitor_wrlock (monitor=0x8050f48) at monitor.c:179
#3 0xb7f94d41 in mu_list_append (list=0x80548b0, item=0x98d2c728) at list.c:92
#4 0xb7f6fc63 in mu_sieve_palloc (pool=0x80547a8, size=8) at util.c:52
#5 0xb7f6fdeb in mu_sieve_malloc (mach=0x80547a0, size=8) at util.c:108
#6 0xb7f69234 in sieve_code_command (reg=0x80596e8, arglist=0x805a428) at
prog.c:202
#7 0xb7f697c7 in sieve_code_action (reg=0x80596e8, arglist=0x805a428) at
prog.c:355
#8 0xb7f6bb8d in mu_sieve_yyparse () at sieve.y:266
#9 0xb7f6c9ba in mu_sieve_compile (mach=0x80547a0, name=0xbfffc660
"XXX.sieve") at sieve.y:603
Any input is highly welcome.
Regards,
Kostas
--
Kostas Zorbadelos
[EMAIL PROTECTED] contact: kzorba (at) otenet.gr
Out there in the darkness, out there in the night
out there in the starlight, one soul burns brighter
than a thousand suns.
--- vacation.c.orig 2006-09-12 11:24:50.000000000 +0300
+++ vacation.c.patched 2006-10-03 17:18:47.233459022 +0300
@@ -399,8 +399,8 @@
{
mu_sieve_value_t *arg;
char *value;
- char *subject;
- int subject_allocated;
+ char *subject = NULL;
+ int subject_allocated = 0;
mu_header_t hdr;
if (mu_sieve_tag_lookup (tags, "subject", &arg))
@@ -449,6 +449,9 @@
free (value);
}
+ if (subject == NULL) /* The original message had no subject or its subject
was empty */
+ subject = "Re: Your mail";
+
if (mu_rfc2047_encode (MU_SIEVE_CHARSET, "quoted-printable",
subject, &value))
mu_header_set_value (newhdr, MU_HEADER_SUBJECT, subject, 0);
/* A sceleton notify action. This is to demonstrate the bug in the
sieve engine's parsing.
Author: Kostas Zorbadelos
Last modification: 3/10/2006
Syntax: notify [:method <url: string>]
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <mailutils/libsieve.h>
/* Produce diagnostic output. */
static int
diag (mu_sieve_machine_t mach)
{
if (mu_sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE)
{
mu_sieve_locus_t locus;
mu_sieve_get_locus (mach, &locus);
mu_sieve_debug (mach, "%s:%lu: NOTIFY\n",
locus.source_file,
(unsigned long) locus.source_line);
}
mu_sieve_log_action (mach, "NOTIFY", NULL);
return mu_sieve_is_dry_run (mach);
}
/* ------------------------------------------------------------------------- */
/* The notify action function */
/* ------------------------------------------------------------------------- */
int
sieve_action_notify (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
mu_sieve_value_t *val;
int status;
mu_sieve_locus_t locus;
char *url;
if (diag (mach))
return 0;
status = mu_sieve_get_locus (mach, &locus);
if (status) /* Cannot get locus ?! */
{
mu_sieve_error (mach, "NOTIFY: Cannot get locus for sieve engine");
return -1;
}
if (mu_sieve_tag_lookup (tags, "method", &val))
{
url = val->v.string;
}
else
{
mu_sieve_error (mach,"%s:%lu: NOTIFY: cannot get :method tag",
locus.source_file,
(unsigned long) locus.source_line);
return -1;
}
return 0;
}
/* Tagged arguments: */
static mu_sieve_tag_def_t notify_tags[] = {
{"method", SVT_STRING},
{NULL}
};
static mu_sieve_tag_group_t notify_tag_groups[] = {
{notify_tags, NULL},
{NULL}
};
/* Required arguments: */
/* There are no required arguments */
static mu_sieve_data_type notify_args[] = {
SVT_VOID
};
int SIEVE_EXPORT (notify, init) (mu_sieve_machine_t mach)
{
return mu_sieve_register_action (mach, "notify", sieve_action_notify,
notify_args, notify_tag_groups, 1);
}
_______________________________________________
Bug-mailutils mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-mailutils