Pārlūkot izejas kodu

Merge branch 'fix-memory-leaks'

* fix-memory-leaks:
  * Cleanup memory leak in chanset 'default' implementation
  * Fix multiple memory leaks in DCC_DNSWAIT cleaning up
  * Fix memory leak in IRC mode parsing
  * Fix possible memory leak in +r lookups
  * Avoid duplicating def_chanset when creating default channel
  * Fix multiple memory leaks in class Tempfile
Bryan Drewery 16 gadi atpakaļ
vecāks
revīzija
23fe2fc528

+ 6 - 0
src/adns.c

@@ -250,6 +250,12 @@ static void kill_dcc_dnswait(int idx, void *x)
   if (p) {
     if (p->cbuf)
       free(p->cbuf);
+
+    if (p->cptr)
+      free(p->cptr);
+    // free(p) is same thing here.
+    free(dcc[idx].u.other);
+    dcc[idx].u.other = NULL;
   }
 }
 

+ 2 - 0
src/botnet.c

@@ -1037,6 +1037,8 @@ static void botlink_dns_callback(int id, void *client_data, const char *host, bd
   if (valid_idx(i)) {
     idx = dcc[i].u.dns->ibuf;
     linker = strdup(dcc[i].u.dns->cptr);
+    free(dcc[i].u.dns->cptr);
+    dcc[i].u.dns->cptr = NULL;
   }
 
   if (!ips.size()) {

+ 6 - 1
src/misc_file.c

@@ -256,6 +256,8 @@ void Tempfile::my_close()
 
 Tempfile::~Tempfile()
 {
+  if (this->prefix)
+    delete[] this->prefix;
   unlink(file);
   my_close();
   delete[] file;
@@ -275,8 +277,11 @@ static bool check_tempdir(bool do_mod)
   Tempfile *testdir = new Tempfile("test");
 
   /* There was an error creating a file in this directory, return to move on in list of dirs */
-  if (!testdir || testdir->error)
+  if (!testdir || testdir->error) {
+    if (testdir)
+      delete testdir;
     return 0;
+  }
 
   fprintf(testdir->f, "\n");
   int result = fflush(testdir->f);

+ 26 - 24
src/mod/channels.mod/channels.c

@@ -698,30 +698,32 @@ static inline bool chanset_unlink(struct chanset_t *chan)
 void remove_channel(struct chanset_t *chan)
 {
    int i;
-   
-   irc_log(chan, "Parting");
-   /* Remove the channel from the list, so that noone can pull it
-      away from under our feet during the check_part() call. */
-   chanset_unlink(chan);
-
-  /* Using chan->name is important here, especially for !chans <cybah> */
-  if (!conf.bot->hub && shouldjoin(chan) && chan->name[0])
-    dprintf(DP_SERVER, "PART %s\n", chan->name);
-
-   clear_channel(chan, 0);
-   noshare = 1;
-   /* Remove channel-bans */
-   while (chan->bans)
-     u_delmask('b', chan, chan->bans->mask, 1);
-   /* Remove channel-exempts */
-   while (chan->exempts)
-     u_delmask('e', chan, chan->exempts->mask, 1);
-   /* Remove channel-invites */
-   while (chan->invites)
-     u_delmask('I', chan, chan->invites->mask, 1);
-   /* Remove channel specific user flags */
-   user_del_chan(chan->dname);
-   noshare = 0;
+
+   if (chan != chanset_default) {
+     irc_log(chan, "Parting");
+     /* Remove the channel from the list, so that noone can pull it
+        away from under our feet during the check_part() call. */
+     chanset_unlink(chan);
+
+    /* Using chan->name is important here, especially for !chans <cybah> */
+    if (!conf.bot->hub && shouldjoin(chan) && chan->name[0])
+      dprintf(DP_SERVER, "PART %s\n", chan->name);
+
+     clear_channel(chan, 0);
+     noshare = 1;
+     /* Remove channel-bans */
+     while (chan->bans)
+       u_delmask('b', chan, chan->bans->mask, 1);
+     /* Remove channel-exempts */
+     while (chan->exempts)
+       u_delmask('e', chan, chan->exempts->mask, 1);
+     /* Remove channel-invites */
+     while (chan->invites)
+       u_delmask('I', chan, chan->invites->mask, 1);
+     /* Remove channel specific user flags */
+     user_del_chan(chan->dname);
+     noshare = 0;
+   }
    free(chan->channel.key);
    for (i = 0; i < MODES_PER_LINE_MAX && chan->cmode[i].op; i++)
      free(chan->cmode[i].op);

+ 10 - 5
src/mod/channels.mod/tclchan.c

@@ -930,8 +930,11 @@ int channel_add(char *result, char *newname, char *options, bool isdefault)
   int items = 0;
   char buf[3001] = "";
 
-  simple_snprintf(buf, sizeof(buf), "chanmode { %s } ", glob_chanmode);
-  strlcat(buf, def_chanset, sizeof(buf));
+  simple_snprintf(buf, sizeof(buf), "chanmode { %s }", glob_chanmode);
+  if (!isdefault) { // These are passed in in 'options'
+    strlcat(buf, " ", sizeof(buf));
+    strlcat(buf, def_chanset, sizeof(buf));
+  }
   // Add in 'default' channel options
   if (!isdefault && chanset_default) {
     bd::String default_chan_options = channel_to_string(chanset_default);
@@ -1005,10 +1008,12 @@ int channel_add(char *result, char *newname, char *options, bool isdefault)
     strlcpy(chan->dname, newname, 81);
 
     /* Initialize chan->channel info */
-    init_channel(chan, 0);
-    if (isdefault)
+    if (isdefault) {
+      if (chanset_default)
+        remove_channel(chanset_default);
       chanset_default = chan;
-    else {
+    } else {
+      init_channel(chan, 0);
       list_append((struct list_type **) &chanset, (struct list_type *) chan);
       /* Channel name is stored in xtra field for sharebot stuff */
       if (!conf.bot->hub && !isdefault)

+ 6 - 1
src/mod/irc.mod/chan.c

@@ -97,7 +97,12 @@ void resolve_to_member(struct chanset_t *chan, char *nick, char *host)
   r->chan = chan;
   r->host = strdup(host);
 
-  egg_dns_lookup(host, 20, resolv_member_callback, (void *) r);
+  if (egg_dns_lookup(host, 20, resolv_member_callback, (void *) r) == -2) { //Already querying?
+    // Querying on clones will cause the callback to not be called and this nick will be ignored
+    // cleanup memory as this chain is not even starting.
+    free(r->host);
+    free(r);
+  }
 }
 
 /* RBL */

+ 19 - 19
src/mod/irc.mod/mode.c

@@ -985,20 +985,20 @@ gotmode(char *from, char *msg)
     /* let's pre-emptively check for mass op/deop, manual ops and cookieops */
 
     if ((channel_active(chan) || channel_pending(chan))) {
-      char *isserver = NULL;
+      char isserver[100] = "";
       size_t z = strlen(msg);
       struct userrec *u = NULL;
       memberlist *m = NULL;
       char *nick = NULL;
 
       if (!strchr(from, '!'))
-        isserver = strdup(from);
+        strlcpy(isserver, from, sizeof(isserver));
 
       if (msg[--z] == ' ')      /* I hate cosmetic bugs :P -poptix */
         msg[z] = 0;
 
       /* Split up from */
-      if (!isserver) {
+      if (!isserver[0]) {
         u = get_user_by_host(from);
         nick = splitnick(&from);
         if ((m = ismember(chan, nick))) {
@@ -1263,77 +1263,77 @@ gotmode(char *from, char *msg)
       for (i = 0; i < modecnt; i++) {
         int todo = 0;
 
-        if (isserver && bounce_modes)
+        if (isserver[0] && bounce_modes)
           reversing = 1;
 
         switch (mmode) {		/* parse mode */
           case 'i':
             todo = CHANINV;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'p':
             todo = CHANPRIV;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 's':
             todo = CHANSEC;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'm':
             todo = CHANMODER;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'c':
             todo = CHANNOCLR;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'C':
             todo = CHANNOCTCP;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'R':
             todo = CHANREGON;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'M':
             todo = CHANMODR;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'r':
             todo = CHANLONLY;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 't':
             todo = CHANTOPIC;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'n':
             todo = CHANNOMSG;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'a':
             todo = CHANANON;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'q':
             todo = CHANQUIET;
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             break;
           case 'l':
-            if (isserver && (bounce_modes))
+            if (isserver[0] && (bounce_modes))
               reversing = 1;
             if (msign == '-') {
               if (channel_active(chan)) {
@@ -1501,7 +1501,7 @@ gotmode(char *from, char *msg)
 
       if (chan->channel.do_opreq)
         request_op(chan);
-      if (!me_op(chan) && isserver)		/* FIXME, WTF IS THIS? */
+      if (!me_op(chan) && isserver[0])		/* FIXME, WTF IS THIS? */
         chan->status |= CHAN_ASKEDMODES;
     }
   }