From 4d9cd019b08e177b872b887715bc390470075b73 Mon Sep 17 00:00:00 2001 From: Anicka Bernathova Date: Fri, 17 Jul 2009 20:56:05 +0200 Subject: [PATCH] fix double free bugs --- code.c | 1 - ham.c | 50 +++++++++++++++++++++- int.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++-------- lex.c | 2 +- umpf.c | 8 ++++ umpf.h | 5 ++- 6 files changed, 176 insertions(+), 23 deletions(-) diff --git a/code.c b/code.c index 4a84d18..18fde4f 100644 --- a/code.c +++ b/code.c @@ -32,7 +32,6 @@ get_bucket_number(char* name) return n; } -/* if not found, variable with value "" is created */ int find_var(char* name, struct list* hash) { diff --git a/ham.c b/ham.c index 4c74d93..714ebc4 100644 --- a/ham.c +++ b/ham.c @@ -70,7 +70,7 @@ make_hlist(void) } last = c; } - //free(buf); + free_string(buf); return l; } @@ -107,7 +107,7 @@ get_body(void) if (fd < 0) { buf = xrealloc(buf, curbufsize *= 2); cannot_save = 1; - free(tmpfile); + free_string(tmpfile); continue; } else { will_save = 1; @@ -269,6 +269,52 @@ copy_email(int fd, struct email* email) return 0; } +int +write_email_to_fd(int fd, struct email* email) +{ + int written; + + /* headers */ + struct hlist* ph; + LIST_FOREACH(ph, email->headers){ + written = write(fd, ph->name, strlen(ph->name)); + if (written < strlen(ph->name)) + return 1; + written = write(fd, ": ", 2); + if (written < 2) + return 1; + written = write(fd, ph->value, strlen(ph->value)); + if (written < strlen(ph->value)) + return 1; + written = write(fd, "\n", 2); + if (written < 1) + return 1; + } + written = write(fd, "\n", 2); + if (written < 1) + return 1; + + /* body */ + + if (email->body) { + written = write(fd, email->body, email->body_len); + if (written < email->body_len) + return 1; + } else { + char buf[MAIL_LEN]; + int i; + for(i = 0; i < email->body_len; i+=MAIL_LEN) { + int len = MAIL_LEN; + if (i >= email->body_len) + len = len - (i - email->body_len); + read(email->fd, buf, len); //FIXME: check it? + write(fd, buf, len); + } + } + + return 0; +} + int deliver_local_email(char* folder, struct email* email) { diff --git a/int.c b/int.c index 7d5fa2e..5215640 100644 --- a/int.c +++ b/int.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "cond.tab.h" #include "umpf.h" @@ -33,11 +34,18 @@ bye(int code, char* msg, ...) exit(code); } +void +free_string(char* c) +{ + if (c != empty) + free(c); +} + static void clear_var(int var) { - if (var_tab[var]) - free(var_tab[var]); + if ((var_tab[var] != NULL)) + free_string(var_tab[var]); } static void @@ -45,15 +53,14 @@ set_var(int var, char* value) { clear_var(var); var_tab[var] = xstrdup(value); - } static char* get_var(int var) { if (var < 0) - return const_tab[-var]; - return var_tab[var]; + return xstrdup(const_tab[-var]); + return xstrdup(var_tab[var]); } /* return var struct or NULL if not found */ @@ -98,15 +105,62 @@ xcat(char* left, char* right) { char* res = xmalloc(strlen(left) + strlen(right) + 1); - strcpy(res,left); - strcat(left,right); + strcpy(res, left); + strcat(res, right); - free(left); - free(right); + free_string(left); + free_string(right); return res; } +static char* +fold(const char* value, int taken) +{ + int i; + char* ret; + int len = strlen(value); + int newlines[len / 78 + 5]; + int newl = 0; + int curr_ws = -1; + int pos = 0; + int newl_done = 0; + + if (len + taken <= 78) + return xstrdup(value); + for(i = 0; i < len; i++) { + if (value[i] == ' ' || value[i]=='\t') + curr_ws = i; + taken++; + if (taken >= 78) { + if (curr_ws > 0){ + newlines[newl++] = curr_ws; + i = curr_ws; + while(value[i] && (value[i] == '\t' + || value[i] == ' ')) + i++; + taken = i - curr_ws; + curr_ws = -1; + } + } + } + ret = xmalloc(2*newl + len + 1); + for (i = 0; i < len; i++) { + if (newl_done == newl) { + strcpy(ret + pos, value + i); + break; + } + if(i != newlines[newl_done]) + ret[pos++] = value[i]; + else { + newl++; + ret[pos++] = '\n'; + ret[pos++] = ' '; + } + } + return ret; +} + static void modify_headers(struct list* headers, struct list* hash) { @@ -121,8 +175,9 @@ modify_headers(struct list* headers, struct list* hash) continue; if (pv->modified){ pv->modified = 0; - free(p->value); - p->value = xstrdup(get_var(pv->varcode)); //FIXME: fold it + free_string(p->value); + p->value = fold(get_var(pv->varcode), + strlen(p->name) + 2); } } @@ -134,7 +189,7 @@ modify_headers(struct list* headers, struct list* hash) p = xmalloc(sizeof(struct hlist)); p->name = xstrdup(pv->name); - p->value = xstrdup(get_var(pv->varcode)); + p->value = get_var(pv->varcode); list_add_last(headers,&p->car); } @@ -187,9 +242,9 @@ static void destroy_email(struct email em) { if (em.body) - free(em.body); + free_string(em.body); if(em.tmpfile) - free(em.tmpfile); + free_string(em.tmpfile); } static void @@ -203,11 +258,14 @@ do_string_ternary_op(struct code* p) case OPC_RE: result = xmalloc(INT_TO_STRING_LEN); sprintf(result, "%d", regex_cmp(l, r)); + break; case OPC_NRE: result = xmalloc(INT_TO_STRING_LEN); sprintf(result, "%d", !regex_cmp(l, r)); + break; case OPC_CAT: result = xcat(l, r); + break; default: break; }; @@ -305,6 +363,42 @@ deliver(char* where, int copy, struct list* hash) } } +static void +send_mail(char* where, int copy, struct list* hash) +{ + int pd[2]; + int pid, status; + int res; + struct email em = prepare_email(hash); + + //write_email_to_fd(1, &em); + res = pipe(pd); + if (res < 0) + goto end; + + if ((pid = fork()) < 0) + goto end; + else if (pid == 0) { + close(0); + dup(pd[0]); + close(pd[0]); + //FIXME From? + res = execl("/usr/lib/sendmail", "sendmail", where, NULL); + } + close(pd[0]); + write_email_to_fd(pd[1], &em); + close(pd[1]); + wait(&status); +end: + destroy_email(em); + if (!copy) { + if (res) + bye(-res, "%m"); + else + bye(0, NULL); + } +} + void interp(struct list* ins, struct list* hash) { @@ -312,8 +406,6 @@ interp(struct list* ins, struct list* hash) char* result; int v; - var_tab = xmalloc(max_varcode * sizeof(char*)); - LIST_FOREACH(p, ins) { switch (p->opcode) { case OPC_SET: @@ -364,6 +456,8 @@ interp(struct list* ins, struct list* hash) case OPC_PIPE: break; case OPC_MAIL: + send_mail(get_var(p->u.arrow.what), + p->u.arrow.copy, hash); break; case OPC_DELIVER: deliver(get_var(p->u.arrow.what), @@ -391,10 +485,10 @@ print_vars(struct list* hash) } static char* -unfold(char* u) +unfold(const char* u) { char* new; - char* pu = u; + const char* pu = u; char* pn; new = xmalloc(strlen(u)+1); @@ -430,8 +524,11 @@ save_current_headers(struct list* hash) pv = get_var_struct(p->name, hash); if (!pv) continue; + if (!get_var(pv->varcode)) + continue; u = unfold(p->value); set_var(pv->varcode, u); + set_var(pv->varcode, p->value); pv->modified = 0; p->have_var = 1; } diff --git a/lex.c b/lex.c index de41693..9f02013 100644 --- a/lex.c +++ b/lex.c @@ -79,7 +79,7 @@ parse_err(char* msg, ...) } char* -xstrdup(char* s) +xstrdup(const char* s) { void* ret; diff --git a/umpf.c b/umpf.c index 3dfef81..19910a4 100644 --- a/umpf.c +++ b/umpf.c @@ -1,4 +1,5 @@ #include +#include #include #include "umpf.h" @@ -11,12 +12,14 @@ init(void) const_tab = xmalloc(BUFSIZE); cur_const_n = 1; cur_const_s = BUFSIZE; + empty = ""; } int main(int argc, char** argv) { int res; + int i; if (argc < 2) die("Usage: ./umpf conf_file [default_mailbox]"); @@ -40,6 +43,11 @@ main(int argc, char** argv) temp_varcode_start = current_varcode; compile(input_tree, NULL); + var_tab = xmalloc((max_varcode + 1) * sizeof(char*)); + for (i = 0; i <= max_varcode; i++) { + var_tab[i] = empty; + } + current_headers = make_hlist(); // print_headers(current_headers); current_body = get_body(); diff --git a/umpf.h b/umpf.h index 2fd1a04..87f5477 100644 --- a/umpf.h +++ b/umpf.h @@ -81,7 +81,7 @@ struct tree* input_tree; #define CC(a,b) ((a<<8)|b) void* xmalloc(size_t size); void* xrealloc(void* buf, size_t size); -char* xstrdup(char* s); +char* xstrdup(const char* s); void __attribute__ ((noreturn)) die(char* msg, ...); void read_conf(char* filename); int line; @@ -174,6 +174,7 @@ char** var_tab; char** const_tab; int cur_const_n; int cur_const_s; +char* empty; void init(void); void compile(struct tree* t, struct list* where); @@ -202,6 +203,7 @@ struct email { void save_current_headers(struct list* hash); void print_vars(struct list* hash); void interp(struct list* ins, struct list* hash); +void free_string(char* c); /* ham.c */ char* default_mailbox; @@ -212,6 +214,7 @@ struct list* make_hlist(void); void print_headers(struct list* l); struct email* get_body(void); int deliver_local_email(char* folder, struct email* email); +int write_email_to_fd(int fd, struct email* email); /* lock.c */ void save_gids(void); -- 2.39.2