]> mj.ucw.cz Git - umpf.git/commitdiff
fix double free bugs
authorAnicka Bernathova <anicka@anicka.net>
Fri, 17 Jul 2009 18:56:05 +0000 (20:56 +0200)
committerAnicka Bernathova <anicka@anicka.net>
Fri, 17 Jul 2009 18:56:05 +0000 (20:56 +0200)
code.c
ham.c
int.c
lex.c
umpf.c
umpf.h

diff --git a/code.c b/code.c
index 4a84d18c7dcc3e2af57a07431b3f4003f4a28cff..18fde4f9f6676e4d0b0d50dae78bcab8f197a957 100644 (file)
--- 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 4c74d937cd3305590ef64fb7e4e82dfa7b88bfee..714ebc4ae51d69340cec30e0be52eebae524d83c 100644 (file)
--- 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 7d5fa2e6ef7aaaf5a3c04197673e2aafd4c3c0a8..521564030369833215e958c7370e3ba5f3e8dc6b 100644 (file)
--- a/int.c
+++ b/int.c
@@ -6,6 +6,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdarg.h>
+#include <sys/wait.h>
 
 #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 de4169321743f7ab65616d47d0bda6e1a3125431..9f0201319dfa47818beeef380a1786f45e8992a5 100644 (file)
--- 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 3dfef8199fb21f047ab9e6b6ba1f6f732e2e8136..19910a4a28376c4e894ab5c62ec491b8d5fbaf76 100644 (file)
--- a/umpf.c
+++ b/umpf.c
@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <string.h>
 #include <pwd.h>
 
 #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 2fd1a04aef2a0e43310e50e199f709500450c4cc..87f5477a9c0d82f3faef23746a2902346f34157a 100644 (file)
--- 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);