SA Bugzilla – Bug 3212
double free in message_cleanup
Last modified: 2004-04-04 11:23:41 UTC
I intermittently get a bad heap in spamc when running the test suite. It seems to be caused by this: message_read_bsmtp() sets m->msg to point *somewhere* in m->raw: i+=6; if(m->raw[i-1]=='\r') i++; m->pre_len=i; m->msg=m->raw+i; ^^ and message_cleanup() attempts to avoid double freeing by testing for (m->out != m->raw) without considering the "i" added by message_read_bsmtp(): void message_cleanup(struct message *m) { if (m->out != NULL && m->out != m->raw) free(m->out); if (m->raw != NULL) free(m->raw); if (m->priv != NULL) free(m->priv); clear_message(m); This is low priority bug. The root of the problem was the the account "nobody" had disappeared. This caused the daemon to shut down prematurely which probably caused spamc to exercise a rare path through the code. Once I had restored the "nobody" account the test worked.
stupid C and it's memory handling! ;) nice catch though. original: if (m->out != NULL && m->out != m->raw) free(m->out); if (m->raw != NULL) free(m->raw); could be changed to: if (m->out != NULL && m->pre != NULL && m->out != m->pre+m->pre_len) free(m->out); if (m->raw != NULL) free(m->raw); from my investigation of the code, m->out will end up getting a malloc() call which will keep it out of the way of m->pre and m->pre_len. but as far as I can tell, m->pre and m->pre_len only get defined and set in message_read_bsmtp, so in theory, they should be safe. thoughts? BTW: as a clarification for the above... by default, raw=null, out=null, pre=null, pre_len=0. in message_read_raw, out=raw. in message_read_bsmtp, out=raw+i, pre=raw, pre_len=i. so in theory, if pre==null, then out==raw, so don't free. if pre!=null, we can see if out==pre+pre_len, which would be the same as out==raw+i, which is how it's set in message_read_bsmtp. so I think that's all right, but my C is very rusty.
ok, I've applied the patch. :) r9864