I'm putting my money where my mouth is: I've modified the 2_0 code and replaced all strdup call with my_strdup call, implemented in debug.c

This my_strdup is a complete ripoff from glib's g_strdup. It uses my_malloc to assign memory allowing full usage of my_free throughout the code.

This also allows clean test runs of the imap-server with garbage collection 
enabled.

I'm updating the debian packages accordingly for 2.0, and will upload 2.0.2-0.20041129 shortly. Those will depend on libgc1 for garbage collection.

Ilja, howabout it: can we start using gc in the codebase starting at 2.0.2?

My double-free fixes don't depend on gc, but gc has helped me trace down some persistent double-free problems. It just seems worth it.

I'm attaching my dpatches for GC and my_strdup for review.

Paul J Stevens wrote:
Some first results are in:

imaputil.c (build_args, build_args_ext) seems to suffer from off-by-one errors triggering out-of-bounds on the args array. They look quite messy, but then they are at the heart of the imap command parser :-\

in many places strings are assigned with strdup, but later free-d with my_free. This causes all kinds of weirdness when re-defining my_malloc/my_free with GC_MALLOC/GC_FREE.

And I havent even started testing the pop3 code.



Paul J Stevens wrote:

As a follow up to myself.

I've been building and testing 2.0.1 a little with garbage collection enabled. Very informative stuff. list.c is definitely prime-suspect.

Thank you Dan Weber for the patch.

Keep you posted.

Paul J Stevens wrote:



Aaron Stone wrote:

Not to crash your crash party, but please make sure to file a bug soon so that we don't forget about this issue until the last minute before 2.0.2.

Meanwhile, I've been keeping an eye on runaway imapd's, and I actually
have quite a lot of them. Just happens that I'm on a dual processor
machine with only a few users, so I don't usually feel the slowdown.




Aaron,

We really need to fix this looping issue. I've been seeing it as well on and off on one of my machines. And mysql's logs start eating disks like hell when this happens.

I'm having that machine send me sms messages and set an at job to restart dbmail when it happens so I can go and attach a gdb to the runaway process, but it's not happening often to do me much good.

It's always perform_imap_search that looping, but I haven't been able to get a real handle on it.

The list.c cleanup and memsetting newset has helped a little it seems. But not enough.

I need automatic backtraces....





--
  ________________________________________________________________
  Paul Stevens                                         [EMAIL PROTECTED]
  NET FACILITIES GROUP                     GPG/PGP: 1024D/11F8CD31
  The Netherlands_______________________________________www.nfg.nl
#! /bin/sh /usr/share/dpatch/dpatch-run
## 01_gc.dpatch by  <[EMAIL PROTECTED]>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.

@DPATCH@
diff -urNad dbmail-2.0.1/acinclude.m4 /tmp/dpep.TCyG3e/dbmail-2.0.1/acinclude.m4
--- dbmail-2.0.1/acinclude.m4   2004-11-29 09:59:14.000000000 +0100
+++ /tmp/dpep.TCyG3e/dbmail-2.0.1/acinclude.m4  2004-11-29 09:59:14.000000000 
+0100
@@ -428,3 +428,66 @@
 fi
 ])
 
+
+# ----------------------------------------------------------------
+# DBMAIL_CHECK_GC
+# I cheated I copied from w3m's acinclude.m4 :)
+# Modified for DBMAIL by Dan Weber
+# ----------------------------------------------------------------
+AC_DEFUN([DBMAIL_CHECK_GC],
+[AC_MSG_CHECKING(for --with-gc)
+AC_ARG_WITH(gc,
+ [  --with-gc[=PREFIX]        libgc PREFIX],
+ [test x"$with_gc" = xno && with_gc="no"],
+ [with_gc="no"])
+ AC_MSG_RESULT($with_gc)
+# Don't check for gc if not appended to command line
+ if test x"$with_gc" = xyes
+ then
+ test x"$with_gc" = xyes && with_gc="/usr /usr/local ${HOME}"
+ unset ac_cv_header_gc_h
+ AC_CHECK_HEADER(gc/gc.h)
+ if test x"$ac_cv_header_gc_h" = xno; then
+   AC_MSG_CHECKING(GC header location)
+   AC_MSG_RESULT($with_gc)
+   gcincludedir=no
+   for dir in $with_gc; do
+     for inc in include include/gc; do
+       cflags="$CFLAGS"
+       CFLAGS="$CFLAGS -I$dir/$inc -DUSE_GC=1"
+       AC_MSG_CHECKING($dir/$inc)
+       unset ac_cv_header_gc_h
+       AC_CHECK_HEADER(gc/gc.h, [gcincludedir="$dir/$inc"; CFLAGS="$CFLAGS 
-I$dir/$inc -DUSE_GC=1"; break])
+       CFLAGS="$cflags"
+     done
+     if test x"$gcincludedir" != xno; then
+       break;
+     fi
+   done
+   if test x"$gcincludedir" = xno; then
+     AC_MSG_ERROR([gc/gc.h not found])
+   fi
+ else
+  cflags="$CFLAGS -DUSE_GC=1"
+  CFLAGS="$cflags"
+ fi
+ unset ac_cv_lib_gc_GC_init
+ AC_CHECK_LIB(gc, GC_init, [LIBS="$LIBS -lgc"])
+ if test x"$ac_cv_lib_gc_GC_init" = xno; then
+    AC_MSG_CHECKING(GC library location)
+    AC_MSG_RESULT($with_gc)
+    gclibdir=no
+    for dir in $with_gc; do
+      ldflags="$LDFLAGS"
+      LDFLAGS="$LDFLAGS -L$dir/lib"
+      AC_MSG_CHECKING($dir)
+      unset ac_cv_lib_gc_GC_init
+      AC_CHECK_LIB(gc, GC_init, [gclibdir="$dir/lib"; LIBS="$LIBS -L$dir/lib 
-lgc"; break])
+      LDFLAGS="$ldflags"
+    done
+    if test x"$gclibdir" = xno; then
+      AC_MSG_ERROR([libgc not found])
+    fi
+ fi
+fi])
+
diff -urNad dbmail-2.0.1/configure.in /tmp/dpep.TCyG3e/dbmail-2.0.1/configure.in
--- dbmail-2.0.1/configure.in   2004-11-29 09:59:14.000000000 +0100
+++ /tmp/dpep.TCyG3e/dbmail-2.0.1/configure.in  2004-11-29 09:59:14.000000000 
+0100
@@ -41,7 +41,8 @@
 DBMAIL_SIEVE_CONF
 DBMAIL_CHECK_SIEVE_LIBS
 DBMAIL_CHECK_GLIB
-
+DBMAIL_CHECK_GC
+ 
 AC_PROG_CC
 AC_COMPILE_WARNINGS
 AC_C_CONST
diff -urNad dbmail-2.0.1/debug.h /tmp/dpep.TCyG3e/dbmail-2.0.1/debug.h
--- dbmail-2.0.1/debug.h        2004-11-29 09:59:13.000000000 +0100
+++ /tmp/dpep.TCyG3e/dbmail-2.0.1/debug.h       2004-11-29 10:09:40.000000000 
+0100
@@ -30,6 +30,11 @@
 #include <sys/syslog.h>
 #include <stdarg.h>
 
+#ifdef USE_GC
+#define GC_DEBUG
+#include <gc/gc.h>
+#endif
+
 #ifndef  _DEBUG_H
 #define  _DEBUG_H
 
@@ -56,9 +61,18 @@
 #define my_free(p) __debug_free(p, __FILE__, __LINE__)
 #define __DEBUG_TRACE_MEMALLOC
 */
+#ifdef USE_GC
+
+#define my_malloc(s) GC_MALLOC(s)
+#define my_free(p) GC_FREE(p)
+
+#else
 
 #define my_malloc(s) malloc(s)
 #define my_free(p) free(p)
+
+#endif
+
 #ifdef __DEBUG_TRACE_MEMALLOC
 #undef __DEBUG_TRACE_MEMALLOC
 #endif
#! /bin/sh /usr/share/dpatch/dpatch-run
## 05_my_strdup.dpatch by  <[EMAIL PROTECTED]>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.

@DPATCH@
diff -urNad dbmail-2.0.1/acl.c /tmp/dpep.GkAS5z/dbmail-2.0.1/acl.c
--- dbmail-2.0.1/acl.c  2004-11-29 16:32:04.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/acl.c 2004-11-29 16:41:40.000000000 +0100
@@ -306,11 +306,11 @@
                /* user is not owner. User will never be granted any right
                   by default, but may be granted any right by setting the
                   right ACL */
-               return strdup("\"\" l r s w i p c d a");
+               return my_strdup("\"\" l r s w i p c d a");
        }
 
        /* user is owner, User will always be granted all rights */
-       return strdup(acl_right_chars);
+       return my_strdup(acl_right_chars);
 }
 
 char *acl_myrights(u64_t userid, u64_t mboxid)
diff -urNad dbmail-2.0.1/config.c /tmp/dpep.GkAS5z/dbmail-2.0.1/config.c
--- dbmail-2.0.1/config.c       2004-11-29 16:32:04.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/config.c      2004-11-29 16:41:40.000000000 
+0100
@@ -98,7 +98,7 @@
                my_free(service_config);
                return -1;
        }
-       service_config->service_name = strdup(serviceName);
+       service_config->service_name = my_strdup(serviceName);
 
        (void) snprintf(service, LINESIZE, "[%s]", serviceName);
 
diff -urNad dbmail-2.0.1/db.c /tmp/dpep.GkAS5z/dbmail-2.0.1/db.c
--- dbmail-2.0.1/db.c   2004-11-29 16:40:43.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/db.c  2004-11-29 16:41:40.000000000 +0100
@@ -548,7 +548,7 @@
        if (db_num_rows() == 0) {
                /* no such user */
                db_free_result();
-               return strdup("");
+               return my_strdup("");
        }
 
        query_result = db_get_result(0, 0);
@@ -557,7 +557,7 @@
                return NULL;
        }
 
-       deliver = strdup(query_result);
+       deliver = my_strdup(query_result);
        db_free_result();
        return deliver;
 }
@@ -759,7 +759,7 @@
        if (db_num_rows() > 0) {
                query_result = db_get_result(0, 0);
                if (query_result && strlen(query_result) > 0) {
-                       *notify_address = strdup(query_result);
+                       *notify_address = my_strdup(query_result);
                        trace(TRACE_DEBUG, "%s,%s: found address [%s]",
                              __FILE__, __func__, *notify_address);
                }
@@ -786,7 +786,7 @@
        if (db_num_rows() > 0) {
                query_result = db_get_result(0, 0);
                if (query_result && strlen(query_result) > 0) {
-                       *reply_body = strdup(query_result);
+                       *reply_body = my_strdup(query_result);
                        trace(TRACE_DEBUG, "%s,%s: found reply_body [%s]",
                              __FILE__, __func__, *reply_body);
                }
@@ -909,7 +909,7 @@
        assert(unique_id);
 
        if (!mailbox)
-               mailbox = strdup("INBOX");
+               mailbox = my_strdup("INBOX");
 
        switch (create_or_error_mailbox) {
        case CREATE_IF_MBOX_NOT_FOUND:
@@ -2372,7 +2372,7 @@
        trace(TRACE_DEBUG, "%s,%s: looking for mailbox with FQN [%s].",
              __FILE__, __func__, fq_name);
 
-       name_str_copy = strdup(fq_name);
+       name_str_copy = my_strdup(fq_name);
        /* see if this is a #User mailbox */
        if ((strlen(NAMESPACE_USER) > 0) &&
            (strstr(fq_name, NAMESPACE_USER) == fq_name)) {
@@ -2430,9 +2430,9 @@
        assert(mailbox_idnr != NULL);
        *mailbox_idnr = 0;
 
-       local_name = strdup(name);
+       local_name = my_strdup(name);
        if (local_name == NULL) {
-               trace(TRACE_ERROR, "%s,%s: error strdup(name). Out of memory?",
+               trace(TRACE_ERROR, "%s,%s: error my_strdup(name). Out of 
memory?",
                      __FILE__, __func__);
                return -1;
        }
@@ -2442,7 +2442,7 @@
        if (db_escape_string(&escaped_local_name, local_name)) {
                trace(TRACE_ERROR, "%s,%s: error escaping local mailbox name.",
                        __FILE__, __func__);
-               free(local_name);
+               my_free(local_name);
                return -1;
        }
        
@@ -2450,7 +2450,7 @@
                 "SELECT mailbox_idnr FROM dbmail_mailboxes "
                 "WHERE name='%s' AND owner_idnr='%llu'",
                 escaped_local_name, owner_idnr);
-       free(local_name); /* allocated with strdup(), so uses normal free() */
+       my_free(local_name);
        my_free(escaped_local_name);
 
        if (db_query(query) == -1) {
@@ -2557,7 +2557,7 @@
        }
        
        for (i = 0; i < n_rows; i++) {
-               all_mailbox_names[i] = strdup(db_get_result(i, 0));
+               all_mailbox_names[i] = my_strdup(db_get_result(i, 0));
                all_mailboxes[i] = db_get_result_u64(i, 1);
                all_mailbox_owners[i] = db_get_result_u64(i, 2);
        } 
@@ -2591,8 +2591,6 @@
                                      __FILE__, __func__,
                                      mailbox_name, mailbox_idnr);
                        }
-                       my_free(mailbox_name);
-                       my_free(all_mailbox_names[i]);
                }
        }
        my_free(all_mailbox_names);
@@ -2871,14 +2869,14 @@
        }
 
        if ((tmp = db_get_result(0, 0))) 
-               mailbox_name = strdup(tmp);
+               mailbox_name = my_strdup(tmp);
        db_free_result();
 
        if (db_escape_string(&escaped_filter, filter) < 0) {
                trace(TRACE_ERROR, "%s,%s: error escaping filter string",
                      __FILE__, __func__);
                if (mailbox_name)
-                       free(mailbox_name);
+                       my_free(mailbox_name);
                return -1;
        }
 
@@ -2888,7 +2886,7 @@
                         "SELECT mailbox_idnr FROM dbmail_mailboxes WHERE name 
LIKE '%s/%s'"
                         " AND owner_idnr = '%llu'",
                         mailbox_name, filter, user_idnr);
-               free(mailbox_name); /* alloc'd with strdup so uses free() */
+               my_free(mailbox_name);
        }
        else
                snprintf(query, DEF_QUERYSIZE,
@@ -3248,11 +3246,10 @@
                *name = '\0';
                return 0;
        }
-       tmp_name = strdup(query_result);
+       tmp_name = my_strdup(query_result);
        
        db_free_result();
-       tmp_fq_name =
-           mailbox_add_namespace(tmp_name, owner_idnr, user_idnr);
+       tmp_fq_name = mailbox_add_namespace(tmp_name, owner_idnr, user_idnr);
        if (!tmp_fq_name) {
                trace(TRACE_ERROR, "%s,%s: error getting fully qualified "
                      "mailbox name", __FILE__, __func__);
diff -urNad dbmail-2.0.1/dbsearch.c /tmp/dpep.GkAS5z/dbmail-2.0.1/dbsearch.c
--- dbmail-2.0.1/dbsearch.c     2004-11-29 16:32:04.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/dbsearch.c    2004-11-29 16:41:40.000000000 
+0100
@@ -96,7 +96,7 @@
  */
 static int num_from_imapdate(const char *date);
 
-int db_search(int *rset, int setlen, const char *key, mailbox_t * mb,
+int db_search(unsigned int *rset, int setlen, const char *key, mailbox_t * mb,
              int type)
 {
        u64_t uid;
@@ -168,7 +168,7 @@
    list_btree_insert(root, curr);
 }
 
-int db_sort_parsed(int *rset, unsigned int setlen,
+int db_sort_parsed(unsigned int *rset, unsigned int setlen,
                      search_key_t *sk, mailbox_t *mb)
 {
 
@@ -212,7 +212,7 @@
     return 0;
 }
 
-int db_search_parsed(int *rset, unsigned int setlen,
+int db_search_parsed(unsigned int *rset, unsigned int setlen,
                     search_key_t * sk, mailbox_t * mb)
 {
        unsigned i;
diff -urNad dbmail-2.0.1/dbsearch.h /tmp/dpep.GkAS5z/dbmail-2.0.1/dbsearch.h
--- dbmail-2.0.1/dbsearch.h     2004-11-29 16:32:59.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/dbsearch.h    2004-11-29 16:41:40.000000000 
+0100
@@ -52,7 +52,7 @@
  *     - 1 on synchronisation error. (search returned a UID which was not
  *     in the MSN-list -> mailbox should be updated
  */
-int db_search(int *rset, int setlen, const char *key, mailbox_t * mb,
+int db_search(unsigned int *rset, int setlen, const char *key, mailbox_t * mb,
              int type);
 
 /**
@@ -66,11 +66,11 @@
  *    - 0 on success
  *    - 1 if mb->exists != setlen
  */
-int db_search_parsed(int *rset, unsigned setlen,
+int db_search_parsed(unsigned int *rset, unsigned setlen,
                     search_key_t * sk, mailbox_t * mb);
 
 
-int db_sort_parsed(int *rset, unsigned setlen, 
+int db_sort_parsed(unsigned int *rset, unsigned setlen, 
                     search_key_t *sk, mailbox_t *mb);
  
 #endif
diff -urNad dbmail-2.0.1/debug.c /tmp/dpep.GkAS5z/dbmail-2.0.1/debug.c
--- dbmail-2.0.1/debug.c        2004-11-29 16:32:04.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/debug.c       2004-11-29 16:41:40.000000000 
+0100
@@ -199,3 +199,20 @@
 
 #endif
 }
+
+
+char * my_strdup(const char *str)
+{
+       char *new_str;
+       size_t length;
+       
+       if (str) {
+               length = strlen(str) + 1;
+               new_str = (char *)my_malloc(length);
+               memcpy(new_str,str,length);
+       } else {
+               new_str = NULL;
+       }
+
+       return new_str;
+}
diff -urNad dbmail-2.0.1/debug.h /tmp/dpep.GkAS5z/dbmail-2.0.1/debug.h
--- dbmail-2.0.1/debug.h        2004-11-29 16:40:43.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/debug.h       2004-11-29 16:41:40.000000000 
+0100
@@ -74,4 +74,5 @@
 
 void __debug_dumpallocs(void);
 
+char * my_strdup(const char *str);
 #endif
diff -urNad dbmail-2.0.1/imapcommands.c 
/tmp/dpep.GkAS5z/dbmail-2.0.1/imapcommands.c
--- dbmail-2.0.1/imapcommands.c 2004-11-29 16:40:44.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/imapcommands.c        2004-11-29 
16:41:40.000000000 +0100
@@ -1594,7 +1594,7 @@
        }
 
        /* find the mailbox to place the message */
-       if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+       if (db_findmailbox((const char *)args[0], ud->userid, &mboxid) == -1) {
                ci_write(ci->tx, "* BYE internal dbase error");
                return -1;
        }
diff -urNad dbmail-2.0.1/imaputil.c /tmp/dpep.GkAS5z/dbmail-2.0.1/imaputil.c
--- dbmail-2.0.1/imaputil.c     2004-11-29 16:32:04.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/imaputil.c    2004-11-29 16:41:40.000000000 
+0100
@@ -1266,7 +1266,8 @@
        int nargs = 0, inquote = 0, i, quotestart = 0;
        int nnorm = 0, nsquare = 0, paridx = 0, slen = 0, argstart = 0;
        char parlist[MAX_LINESIZE];
-
+       unsigned int argsize = 0;
+       
        if (!s)
                return NULL;
 
@@ -1287,27 +1288,22 @@
                /* check quotes */
                if (s[i] == '"' && ((i > 0 && s[i - 1] != '\\') || i == 0)) {
                        if (inquote) {
+                               argsize = i - quotestart -1; // avoid copying "
+                               
                                /* quotation end, treat quoted string as 
argument */
-                               if (!
-                                   (the_args[nargs] =
-                                    (char *) my_malloc(sizeof(char) *
-                                                       (i -
-                                                        quotestart)))) {
+                               
+                               if (!  (the_args[nargs] = (char *) 
my_malloc(sizeof(char) * argsize + 1))) {
                                        /* out of mem */
                                        while (--nargs >= 0) {
                                                my_free(the_args[nargs]);
                                                the_args[nargs] = NULL;
                                        }
 
-                                       trace(TRACE_ERROR,
-                                             "IMAPD: Not enough memory while 
building up argument array.");
+                                       trace(TRACE_ERROR, "IMAPD: Not enough 
memory while building up argument array.");
                                        return NULL;
                                }
-
-                               memcpy((void *) the_args[nargs], 
-                                      (void *) &s[quotestart + 1],
-                                      i - quotestart - 1);
-                               the_args[nargs][i - quotestart - 1] = '\0';
+                               memset((void *)the_args[nargs],'\0', argsize + 
1);
+                               memcpy((void *) the_args[nargs], (void *) 
&s[quotestart+1], argsize);
 
                                nargs++;
                                inquote = 0;
@@ -1323,20 +1319,17 @@
                        continue;
 
                /* check for (, ), [ or ] in string */
-               if (s[i] == '(' || s[i] == ')' || s[i] == '['
-                   || s[i] == ']') {
+               if (s[i] == '(' || s[i] == ')' || s[i] == '[' || s[i] == ']') {
                        /* check parenthese structure */
                        if (s[i] == ')') {
-                               if (paridx < 0
-                                   || parlist[paridx] != NORMPAR)
+                               if (paridx < 0 || parlist[paridx] != NORMPAR)
                                        paridx = -1;
                                else {
                                        nnorm--;
                                        paridx--;
                                }
                        } else if (s[i] == ']') {
-                               if (paridx < 0
-                                   || parlist[paridx] != SQUAREPAR)
+                               if (paridx < 0 || parlist[paridx] != SQUAREPAR)
                                        paridx = -1;
                                else {
                                        paridx--;
@@ -1361,17 +1354,13 @@
                        }
 
                        /* add this parenthesis to the arg list and continue */
-                       if (!
-                           (the_args[nargs] =
-                            (char *) my_malloc(sizeof(" ")))) {
+                       if (!  (the_args[nargs] = (char *) my_malloc(sizeof(" 
") + 1))) {
                                /* out of mem */
                                while (--nargs >= 0) {
                                        my_free(the_args[nargs]);
                                        the_args[nargs] = NULL;
                                }
-
-                               trace(TRACE_ERROR,
-                                     "IMAPD: Not enough memory while building 
up argument array.");
+                               trace(TRACE_ERROR, "IMAPD: Not enough memory 
while building up argument array.");
                                return NULL;
                        }
                        the_args[nargs][0] = s[i];
@@ -1395,25 +1384,19 @@
                                else
                                        break;
                        }
-
-               if (!
-                   (the_args[nargs] =
-                    (char *) my_malloc(sizeof(char) *
-                                       (i - argstart + 1)))) {
+               argsize = i - argstart; // no +1 here to avoid copying delimiter
+               if (!  (the_args[nargs] = (char *) my_malloc(sizeof(char) * 
argsize + 1))) {
                        /* out of mem */
                        while (--nargs >= 0) {
                                my_free(the_args[nargs]);
                                the_args[nargs] = NULL;
                        }
 
-                       trace(TRACE_ERROR,
-                             "IMAPD: Not enough memory while building up 
argument array.");
+                       trace(TRACE_ERROR, "IMAPD: Not enough memory while 
building up argument array.");
                        return NULL;
                }
-
-               memcpy((void *) the_args[nargs], (void *) &s[argstart], 
-                      i - argstart);
-               the_args[nargs][i - argstart] = '\0';
+               memset((void *) the_args[nargs], '\0', argsize + 1);
+               memcpy((void *) the_args[nargs], (void *) &s[argstart], 
argsize);
 
                nargs++;
                i--;            /* walked one too far */
@@ -1451,6 +1434,7 @@
        char s[MAX_LINESIZE];
        char *tmp, *lastchar;
        int quotedSize, cnt, dataidx;
+       int argsize=0;
 
        /* this is done for the possible extra lines to be read from the client:
         * the line is read into currline; s will always point to the line 
currently
@@ -1477,27 +1461,20 @@
                /* check quotes */
                if (s[i] == '"' && ((i > 0 && s[i - 1] != '\\') || i == 0)) {
                        if (inquote) {
+                               argsize = i - quotestart - 1; // avoid copying "
                                /* quotation end, treat quoted string as 
argument */
-                               if (!
-                                   (the_args[nargs] =
-                                    (char *) my_malloc(sizeof(char) *
-                                                       (i -
-                                                        quotestart)))) {
+                               if (!  (the_args[nargs] = (char *) 
my_malloc(sizeof(char) * argsize + 1))) {
                                        /* out of mem */
                                        while (--nargs >= 0) {
                                                my_free(the_args[nargs]);
                                                the_args[nargs] = NULL;
                                        }
 
-                                       trace(TRACE_ERROR,
-                                             "IMAPD: Not enough memory while 
building up argument array.");
+                                       trace(TRACE_ERROR, "IMAPD: Not enough 
memory while building up argument array.");
                                        return NULL;
                                }
-
-                               memcpy((void *) the_args[nargs], 
-                                      (void *) &s[quotestart + 1],
-                                      i - quotestart - 1);
-                               the_args[nargs][i - quotestart - 1] = '\0';
+                               memset((void *) the_args[nargs], '\0', argsize 
+ 1);
+                               memcpy((void *) the_args[nargs], (void *) 
&s[quotestart + 1], argsize);
 
                                nargs++;
                                inquote = 0;
@@ -1513,20 +1490,17 @@
                        continue;
 
                /* check for (, ), [ or ] in string */
-               if (s[i] == '(' || s[i] == ')' || s[i] == '['
-                   || s[i] == ']') {
+               if (s[i] == '(' || s[i] == ')' || s[i] == '[' || s[i] == ']') {
                        /* check parenthese structure */
                        if (s[i] == ')') {
-                               if (paridx < 0
-                                   || parlist[paridx] != NORMPAR)
+                               if (paridx < 0 || parlist[paridx] != NORMPAR)
                                        paridx = -1;
                                else {
                                        nnorm--;
                                        paridx--;
                                }
                        } else if (s[i] == ']') {
-                               if (paridx < 0
-                                   || parlist[paridx] != SQUAREPAR)
+                               if (paridx < 0 || parlist[paridx] != SQUAREPAR)
                                        paridx = -1;
                                else {
                                        paridx--;
@@ -1551,9 +1525,7 @@
                        }
 
                        /* add this parenthesis to the arg list and continue */
-                       if (!
-                           (the_args[nargs] =
-                            (char *) my_malloc(sizeof(" ")))) {
+                       if (!  (the_args[nargs] = (char *) my_malloc(sizeof(" 
") + 1))) {
                                /* out of mem */
                                while (--nargs >= 0) {
                                        my_free(the_args[nargs]);
@@ -1583,12 +1555,9 @@
                        if ((*lastchar == '+' && *(lastchar + 1) == '}' && 
                             *(lastchar + 2) == '\0') || 
                            (*lastchar == '}' && *(lastchar + 1) == '\0')) {
+                               argsize = quotedSize + 1;
                                /* allocate space for this argument (could be a 
message when used with APPEND) */
-                               if (!
-                                   (the_args[nargs] =
-                                    (char *) my_malloc(sizeof(char) *
-                                                       (quotedSize +
-                                                        1)))) {
+                               if (!  (the_args[nargs] = (char *) 
my_malloc(sizeof(char) * argsize + 1))) {
                                        /* out of mem */
                                        while (--nargs >= 0) {
                                                my_free(the_args[nargs]);
@@ -1597,37 +1566,31 @@
 
                                        trace(TRACE_ERROR,
                                              "build_args_array_ext(): out of 
memory allocating [%u] bytes for extra string",
-                                             quotedSize + 1);
+                                             argsize);
                                        return NULL;
                                }
-
-                               fprintf(ci->tx,
-                                       "+ OK gimme that string\r\n");
+                               memset((void *)the_args[nargs],'\0', argsize + 
1);
+                               
+                               fprintf(ci->tx, "+ OK gimme that string\r\n");
                                alarm(ci->timeout);     /* dont wait forever */
-                               for (cnt = 0, dataidx = 0;
-                                    cnt < quotedSize; cnt++) {
-                                       the_args[nargs][dataidx] =
-                                           fgetc(ci->rx);
+                               for (cnt = 0, dataidx = 0; cnt < quotedSize; 
cnt++) {
+                                       the_args[nargs][dataidx] = 
fgetc(ci->rx);
 
-                                       if (the_args[nargs][dataidx] !=
-                                           '\r')
+                                       if (the_args[nargs][dataidx] != '\r')
                                                dataidx++;      /* only store 
if it is not \r */
                                }
 
                                alarm(0);
-                               the_args[nargs][dataidx] = '\0';        /* 
terminate string */
                                nargs++;
 
-                               if (!ci->rx || !ci->tx || ferror(ci->rx)
-                                   || ferror(ci->tx)) {
+                               if (!ci->rx || !ci->tx || ferror(ci->rx) || 
ferror(ci->tx)) {
                                        /* timeout occurred or connection has 
gone away */
                                        while (--nargs >= 0) {
                                                my_free(the_args[nargs]);
                                                the_args[nargs] = NULL;
                                        }
 
-                                       trace(TRACE_ERROR,
-                                             "build_args_array_ext(): timeout 
occurred");
+                                       trace(TRACE_ERROR, 
"build_args_array_ext(): timeout occurred");
                                        return NULL;
                                }
 
@@ -1636,31 +1599,26 @@
                                fgets(s, MAX_LINESIZE, ci->rx);
                                alarm(0);
 
-                               if (!ci->rx || !ci->tx || ferror(ci->rx)
-                                   || ferror(ci->tx)) {
+                               if (!ci->rx || !ci->tx || ferror(ci->rx) || 
ferror(ci->tx)) {
                                        /* timeout occurred */
                                        while (--nargs >= 0) {
                                                my_free(the_args[nargs]);
                                                the_args[nargs] = NULL;
                                        }
 
-                                       trace(TRACE_ERROR,
-                                             "build_args_array_ext(): timeout 
occurred");
+                                       trace(TRACE_ERROR, 
"build_args_array_ext(): timeout occurred");
                                        return NULL;
                                }
 
                                /* remove trailing \r\n */
                                tmp = &s[strlen(s)];
                                tmp--;  /* go before trailing \0; watch this 
with empty strings! */
-                               while (tmp >= s
-                                      && (*tmp == '\r' || *tmp == '\n')) {
+                               while (tmp >= s && (*tmp == '\r' || *tmp == 
'\n')) {
                                        *tmp = '\0';
                                        tmp--;
                                }
 
-                               trace(TRACE_DEBUG,
-                                     "build_args_array_ext(): got extra line 
[%s]",
-                                     s);
+                               trace(TRACE_DEBUG, "build_args_array_ext(): got 
extra line [%s]", s);
 
                                /* start over! */
                                i = 0;
@@ -1680,11 +1638,8 @@
                                else
                                        break;
                        }
-
-               if (!
-                   (the_args[nargs] =
-                    (char *) my_malloc(sizeof(char) *
-                                       (i - argstart + 1)))) {
+               argsize = i - argstart; // no +1 here to avoid copying 
delimiter.
+               if (!  (the_args[nargs] = (char *) my_malloc(sizeof(char) * 
argsize + 1))) {
                        /* out of mem */
                        while (--nargs >= 0) {
                                my_free(the_args[nargs]);
@@ -1695,10 +1650,8 @@
                              "IMAPD: Not enough memory while building up 
argument array.");
                        return NULL;
                }
-
-               memcpy((void *) the_args[nargs], (void *) &s[argstart], 
-                      i - argstart);
-               the_args[nargs][i - argstart] = '\0';
+               memset((void *) the_args[nargs], '\0', argsize + 1);
+               memcpy((void *) the_args[nargs], (void *) &s[argstart], 
argsize);
 
                nargs++;
                i--;            /* walked one too far */
@@ -2648,12 +2601,13 @@
  * returns 0 on succes, -1 on dbase error, -2 on memory error, 1 if result set 
is too small
  * (new mail has been added to mailbox while searching, mailbox data out of 
sync)
  */
-int perform_imap_search(int *rset, int setlen, search_key_t * sk,
+int perform_imap_search(unsigned int *rset, int setlen, search_key_t * sk,
                        mailbox_t * mb, int sorted)
 {
        search_key_t *subsk;
        struct element *el;
-       int result, *newset = NULL, i;
+       int result, i;
+       unsigned int *newset = NULL;
        int subtype = IST_SUBSEARCH_OR;
 
        if (!rset)
@@ -2662,7 +2616,7 @@
        if (!sk)
                return 0;       /* no search */
 
-       newset = (int *) my_malloc(sizeof(int) * setlen);
+       newset = (unsigned int *) my_malloc(sizeof(unsigned int) * setlen);
        
        if (!newset)
                return -2;
@@ -2796,7 +2750,7 @@
 }
 
 
-void invert_set(int *set, int setlen)
+void invert_set(unsigned int *set, int setlen)
 {
        int i;
 
@@ -2808,7 +2762,7 @@
 }
 
 
-void combine_sets(int *dest, int *sec, int setlen, int type)
+void combine_sets(unsigned int *dest, unsigned int *sec, int setlen, int type)
 {
        int i;
 
@@ -2831,7 +2785,7 @@
  * builds a msn-set from a IMAP message set spec. the IMAP set is supposed to 
be correct,
  * no checks are performed.
  */
-void build_set(int *set, unsigned int setlen, char *cset)
+void build_set(unsigned int *set, unsigned int setlen, char *cset)
 {
        unsigned int i;
        u64_t num, num2;
@@ -2901,7 +2855,7 @@
  *
  * as build_set() but takes uid's instead of MSN's
  */
-void build_uid_set(int *set, unsigned int setlen, char *cset,
+void build_uid_set(unsigned int *set, unsigned int setlen, char *cset,
                   mailbox_t * mb)
 {
        unsigned int i, msn, msn2;
diff -urNad dbmail-2.0.1/imaputil.h /tmp/dpep.GkAS5z/dbmail-2.0.1/imaputil.h
--- dbmail-2.0.1/imaputil.h     2004-11-29 16:32:59.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/imaputil.h    2004-11-29 16:41:40.000000000 
+0100
@@ -81,15 +81,15 @@
 void send_data(FILE * to, MEM * from, int cnt);
 
 int build_imap_search(char **search_keys, struct list *sl, int *idx, int 
sorted);
-int perform_imap_search(int *rset, int setlen, search_key_t * sk,
+int perform_imap_search(unsigned int *rset, int setlen, search_key_t * sk,
                        mailbox_t * mb, int sorted);
 void free_searchlist(struct list *sl);
 
-void invert_set(int *set, int setlen);
-void combine_sets(int *dest, int *sec, int setlen, int type);
+void invert_set(unsigned int *set, int setlen);
+void combine_sets(unsigned int *dest, unsigned int *sec, int setlen, int type);
 
-void build_set(int *set, unsigned int setlen, char *cset);
-void build_uid_set(int *set, unsigned int setlen, char *cset,
+void build_set(unsigned int *set, unsigned int setlen, char *cset);
+void build_uid_set(unsigned int *set, unsigned int setlen, char *cset,
                   mailbox_t * mb);
 void dumpsearch(search_key_t * sk, int level);
 
diff -urNad dbmail-2.0.1/list.c /tmp/dpep.GkAS5z/dbmail-2.0.1/list.c
--- dbmail-2.0.1/list.c 2004-11-29 16:32:04.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/list.c        2004-11-29 16:41:40.000000000 
+0100
@@ -248,7 +248,7 @@
                list_btree_printout(tree->right, i);
 }
 
-void list_btree_traverse(sortitems_t * tree, int * i, int *rset) {
+void list_btree_traverse(sortitems_t * tree, int * i, unsigned int *rset) {
        if(tree->left) 
                list_btree_traverse(tree->left, i, rset);
        trace(TRACE_DEBUG, "list_btree_traverse: i '%d' '%d', '%s'\n", 
diff -urNad dbmail-2.0.1/list.h /tmp/dpep.GkAS5z/dbmail-2.0.1/list.h
--- dbmail-2.0.1/list.h 2004-11-29 16:32:59.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/list.h        2004-11-29 16:41:40.000000000 
+0100
@@ -73,7 +73,7 @@
 
 void list_btree_insert(sortitems_t ** tree, sortitems_t * item);
 void list_btree_printout(sortitems_t * tree, int *i);
-void list_btree_traverse(sortitems_t * tree, int * i, int *rset);
+void list_btree_traverse(sortitems_t * tree, int * i, unsigned int *rset);
 void list_btree_free(sortitems_t * tree);
 
 #endif
diff -urNad dbmail-2.0.1/main.c /tmp/dpep.GkAS5z/dbmail-2.0.1/main.c
--- dbmail-2.0.1/main.c 2004-11-29 16:32:05.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/main.c        2004-11-29 16:41:40.000000000 
+0100
@@ -248,7 +248,7 @@
                              "main(): using SPECIAL_DELIVERY to usernames");
 
                        dsnuser_init(&dsnuser);
-                       dsnuser.address = strdup(optarg);
+                       dsnuser.address = my_strdup(optarg);
 
                        /* Add argument onto the users list. */
                        if (list_nodeadd
@@ -268,7 +268,7 @@
                              "main(): using SPECIAL_DELIVERY to email 
addresses");
 
                        dsnuser_init(&dsnuser);
-                       dsnuser.address = strdup(optarg);
+                       dsnuser.address = my_strdup(optarg);
 
                        /* Add argument onto the users list. */
                        if (list_nodeadd
@@ -426,7 +426,7 @@
                        deliver_to_user_t dsnuser;
 
                        dsnuser_init(&dsnuser);
-                       dsnuser.address = strdup((char *) tmp->data);
+                       dsnuser.address = my_strdup((char *) tmp->data);
 
                        list_nodeadd(&dsnusers, &dsnuser,
                                     sizeof(deliver_to_user_t));
@@ -440,7 +440,7 @@
                /* Loop through the dsnusers list, setting the destination 
mailbox. */
                for (tmp = list_getstart(&dsnusers); tmp != NULL;
                     tmp = tmp->nextnode) {
-                       ((deliver_to_user_t *)tmp->data)->mailbox = 
strdup(deliver_to_mailbox);
+                       ((deliver_to_user_t *)tmp->data)->mailbox = 
my_strdup(deliver_to_mailbox);
                }
        }
 
diff -urNad dbmail-2.0.1/mime.c /tmp/dpep.GkAS5z/dbmail-2.0.1/mime.c
--- dbmail-2.0.1/mime.c 2004-11-29 16:32:05.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/mime.c        2004-11-29 16:41:40.000000000 
+0100
@@ -74,7 +74,7 @@
 
        trace(TRACE_DEBUG, "mime_readheader(): entering mime loop");
 
-       blkdata = strdup(datablock);
+       blkdata = my_strdup(datablock);
 
        list_init(mimelist);
        *headersize = 0;
@@ -83,7 +83,7 @@
                trace(TRACE_DEBUG,
                      "mime_readheader(): found an empty header\n");
                (*blkidx)++;    /* skip \n */
-               free(blkdata);
+               my_free(blkdata);
                return 1;       /* found 1 newline */
        }
 
@@ -92,7 +92,7 @@
 
        if (!mr) {
                trace(TRACE_ERROR, "mime_readheader(): out of memory\n");
-               free(blkdata);
+               my_free(blkdata);
                return -2;
        }
 
@@ -123,7 +123,7 @@
                        /* end of data block reached (??) */
                        my_free(mr);
                        *blkidx += (endptr - startptr);
-                       free(blkdata);
+                       my_free(blkdata);
                        return totallines;
                }
 
@@ -196,7 +196,7 @@
                                trace(TRACE_ERROR,
                                      "mime_readheader(): cannot add element to 
list\n");
                                my_free(mr);
-                               free(blkdata);
+                               my_free(blkdata);
                                return -2;
                        }
 
@@ -244,7 +244,7 @@
                                        trace(TRACE_ERROR,
                                              "mime_readheader(): cannot add 
element to list\n");
                                        my_free(mr);
-                                       free(blkdata);
+                                       my_free(blkdata);
                                        return -2;
                                }
                        } else {
@@ -289,7 +289,7 @@
                              "mime_readheader(): found double newline; header 
size: %d lines\n",
                              totallines);
                        my_free(mr);
-                       free(blkdata);
+                       my_free(blkdata);
                        return totallines;
                }
 
@@ -303,11 +303,11 @@
        if (valid_mime_lines < 2) {
                trace(TRACE_ERROR,
                      "mime_readheader(): no valid mime headers found\n");
-               free(blkdata);
+               my_free(blkdata);
                return -1;
        }
 
-       free(blkdata);
+       my_free(blkdata);
        /* success ? */
        trace(TRACE_DEBUG, " *** mime_readheader() done ***\n");
        return totallines;
diff -urNad dbmail-2.0.1/misc.c /tmp/dpep.GkAS5z/dbmail-2.0.1/misc.c
--- dbmail-2.0.1/misc.c 2004-11-29 16:32:05.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/misc.c        2004-11-29 16:41:40.000000000 
+0100
@@ -130,7 +130,7 @@
 
        if (user_idnr == owner_idnr) {
                /* mailbox owned by current user */
-               return strdup(mailbox_name);
+               return my_strdup(mailbox_name);
        } else {
                owner_name = auth_get_userid(owner_idnr);
                if (owner_name == NULL) {
@@ -357,7 +357,7 @@
        /* If there are more strings, copy those, too */
        for (i = j = n = 0; i <= len_decoded; i++) {
                if (str_decoded[i] == '\0') {
-                       ret[n] = strdup(str_decoded + j);
+                       ret[n] = my_strdup(str_decoded + j);
                        j = i + 1;
                        n++;
                }
diff -urNad dbmail-2.0.1/quota.c /tmp/dpep.GkAS5z/dbmail-2.0.1/quota.c
--- dbmail-2.0.1/quota.c        2004-11-29 16:32:05.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/quota.c       2004-11-29 16:41:40.000000000 
+0100
@@ -71,7 +71,7 @@
 int quota_set_root(quota_t * quota, char *root)
 {
        my_free(quota->root);
-       quota->root = strdup(root);
+       quota->root = my_strdup(root);
        return (quota->root == NULL);
 }
 
diff -urNad dbmail-2.0.1/sievecmd.c /tmp/dpep.GkAS5z/dbmail-2.0.1/sievecmd.c
--- dbmail-2.0.1/sievecmd.c     2004-11-29 16:32:05.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/sievecmd.c    2004-11-29 16:41:40.000000000 
+0100
@@ -88,7 +88,7 @@
                        source = stdin; // FIXME to take files as input, too
                        break;
                case 'u':
-                       user_name = strdup(optarg);
+                       user_name = my_strdup(optarg);
                        break;
                case 'l':
                        if (act != 0)
@@ -164,7 +164,7 @@
        }
 
       mainend:
-       free(user_name);
+       my_free(user_name);
        db_disconnect();
        auth_disconnect();
        return res;
diff -urNad dbmail-2.0.1/smtp-convert.c 
/tmp/dpep.GkAS5z/dbmail-2.0.1/smtp-convert.c
--- dbmail-2.0.1/smtp-convert.c 2004-11-29 16:40:43.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/smtp-convert.c        2004-11-29 
16:41:40.000000000 +0100
@@ -149,9 +149,9 @@
                                        namelist[n]->d_name);
                                traverse(newpath);
                        }
-                       free(namelist[n]);
+                       my_free(namelist[n]);
                }
-               free(namelist);
+               my_free(namelist);
        }
        return 0;
 }
diff -urNad dbmail-2.0.1/sort/sortsieve.c 
/tmp/dpep.GkAS5z/dbmail-2.0.1/sort/sortsieve.c
--- dbmail-2.0.1/sort/sortsieve.c       2004-11-29 16:32:22.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/sort/sortsieve.c      2004-11-29 
16:41:40.000000000 +0100
@@ -250,7 +250,7 @@
                                printf("Destination is %s\n",
                                       context->addr);
                                tmpmeth = SA_REDIRECT;
-                               tmpdest = strdup(context->addr);
+                               tmpdest = my_strdup(context->addr);
                                break;
                        }
                case SIEVE2_ACTION_REJECT:
@@ -261,7 +261,7 @@
                                printf("Action is REJECT: ");
                                printf("Message is %s\n", context->msg);
                                tmpmeth = SA_REJECT;
-                               tmpmsg = strdup(context->msg);
+                               tmpmsg = my_strdup(context->msg);
                                break;
                        }
                case SIEVE2_ACTION_DISCARD:
@@ -277,7 +277,7 @@
                                printf("Destination is %s\n",
                                       context->mailbox);
                                tmpmeth = SA_FILEINTO;
-                               tmpdest = strdup(context->mailbox);
+                               tmpdest = my_strdup(context->mailbox);
                                break;
                        }
                case SIEVE2_ACTION_NOTIFY:
diff -urNad dbmail-2.0.1/timsieve.c /tmp/dpep.GkAS5z/dbmail-2.0.1/timsieve.c
--- dbmail-2.0.1/timsieve.c     2004-11-29 16:32:05.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/timsieve.c    2004-11-29 16:41:40.000000000 
+0100
@@ -409,13 +409,13 @@
                                                                session->
                                                                    username
                                                                    =
-                                                                   strdup
+                                                                   my_strdup
                                                                    (tmp64
                                                                     [1]);
                                                                session->
                                                                    password
                                                                    =
-                                                                   strdup
+                                                                   my_strdup
                                                                    (tmp64
                                                                     [2]);
                                                        } else {
diff -urNad dbmail-2.0.1/user.c /tmp/dpep.GkAS5z/dbmail-2.0.1/user.c
--- dbmail-2.0.1/user.c 2004-11-29 16:32:05.000000000 +0100
+++ /tmp/dpep.GkAS5z/dbmail-2.0.1/user.c        2004-11-29 16:41:40.000000000 
+0100
@@ -457,7 +457,7 @@
                        if (pw[len-1] == '\n')
                                pw[len-1] = '\0';
                        /* fgets guarantees a nul terminated string. */
-                       passwd = strdup(pw);
+                       passwd = my_strdup(pw);
 
                        /* Restore the previous terminal state (with echo back 
on). */
                        tcsetattr(fileno(stdin), TCSANOW, &oldattr);
@@ -743,7 +743,7 @@
        }
 
        /* Pass this out of the function. */
-       *password = strdup(pw);
+       *password = my_strdup(pw);
 
        return result;
 }

Reply via email to