Fix uninitialized mod_chanmode element in debug build
[srvx.git] / src / proto-common.c
index d5ebc8ac4a55e42409efec447cd77da134b6aa6c..5a7a689ca2c5f639684b02c0c9aa9d9ba23523a4 100644 (file)
@@ -1,11 +1,12 @@
 /* proto-common.c - common IRC protocol parsing/sending support
  * Copyright 2000-2004 srvx Development Team
  *
- * This program is free software; you can redistribute it and/or modify
+ * This file is part of srvx.
+ *
+ * srvx is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.  Important limitations are
- * listed in the COPYING file that accompanies this software.
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,7 +14,8 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, email srvx-maintainers@srvx.net.
+ * along with srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
 
 #include "conf.h"
@@ -519,8 +521,12 @@ mod_chanmode_alloc(unsigned int argc)
         res = calloc(1, sizeof(*res) + (argc-1)*sizeof(res->args[0]));
     else
         res = calloc(1, sizeof(*res));
-    if (res)
+    if (res) {
+#if !defined(NDEBUG)
+        res->alloc_argc = argc;
+#endif
         res->argc = argc;
+    }
     return res;
 }
 
@@ -532,6 +538,8 @@ mod_chanmode_dup(struct mod_chanmode *orig, unsigned int extra)
     if (res) {
         res->modes_set = orig->modes_set;
         res->modes_clear = orig->modes_clear;
+        res->new_limit = orig->new_limit;
+        memcpy(res->new_key, orig->new_key, sizeof(res->new_key));
         res->argc = orig->argc;
         memcpy(res->args, orig->args, orig->argc*sizeof(orig->args[0]));
     }
@@ -544,6 +552,7 @@ mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_ch
     struct banNode *bn;
     unsigned int ii, jj;
 
+    assert(change->argc <= change->alloc_argc);
     channel->modes = (channel->modes & ~change->modes_clear) | change->modes_set;
     if (change->modes_set & MODE_LIMIT)
         channel->limit = change->new_limit;
@@ -578,13 +587,20 @@ mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_ch
                 break;
             }
             break;
-        default:
-            assert((change->args[ii].mode & (MODE_REMOVE|MODE_CHANOP|MODE_VOICE)) != 0);
+        case MODE_CHANOP:
+        case MODE_VOICE:
+        case MODE_VOICE|MODE_CHANOP:
+        case MODE_REMOVE|MODE_CHANOP:
+        case MODE_REMOVE|MODE_VOICE:
+        case MODE_REMOVE|MODE_VOICE|MODE_CHANOP:
             if (change->args[ii].mode & MODE_REMOVE)
                 change->args[ii].member->modes &= ~change->args[ii].mode;
             else
                 change->args[ii].member->modes |= change->args[ii].mode;
             break;
+        default:
+            assert(0 && "Invalid mode argument");
+            continue;
         }
     }
 }
@@ -619,8 +635,8 @@ mod_chanmode(struct userNode *who, struct chanNode *channel, char **modes, unsig
 int
 irc_make_chanmode(struct chanNode *chan, char *out) {
     struct mod_chanmode change;
+    mod_chanmode_init(&change);
     change.modes_set = chan->modes;
-    change.modes_clear = change.argc = 0;
     change.new_limit = chan->limit;
     safestrncpy(change.new_key, chan->key, sizeof(change.new_key));
     return strlen(mod_chanmode_format(&change, out));