handle errors nicely: warn without crashing - surf-adblock - Surf adblock web extension
 (HTM) git clone git://git.codemadness.org/surf-adblock
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 9014575ee36dc784da9f519c41d44932d248b772
 (DIR) parent 8f646ec95953602d0667766aa81e1a329ff05d13
 (HTM) Author: Quentin Rameau <quinq@fifth.space>
       Date:   Sun, 17 Jul 2016 14:33:04 +0200
       
       handle errors nicely: warn without crashing
       
       We don't want to crash the whole webprocess on error (do we?).
       Warn when an error happened and bail out.
       
       Diffstat:
         M surf-adblock.c                      |     166 ++++++++++++++++++-------------
       
       1 file changed, 98 insertions(+), 68 deletions(-)
       ---
 (DIR) diff --git a/surf-adblock.c b/surf-adblock.c
       @@ -72,10 +72,10 @@ struct filtertype {
                int allowinverse;
                int allownormal;
                int onlyexception;
       -        void (*fn)(struct filterrule *, char *);
       +        int (*fn)(struct filterrule *, char *);
        };
        
       -static void parsedomainsoption(struct filterrule *, char *);
       +static int parsedomainsoption(struct filterrule *, char *);
        
        #define STRP(s) s,sizeof(s)-1
        
       @@ -123,74 +123,73 @@ weprintf(const char *fmt, ...)
                va_end(ap);
        }
        
       -static void
       -eprintf(const char *fmt, ...)
       -{
       -        va_list ap;
       -
       -        fprintf(stderr, "surf-adblock: ");
       -
       -        va_start(ap, fmt);
       -        vfprintf(stderr, fmt, ap);
       -        va_end(ap);
       -
       -        exit(1);
       -}
       -
       -static void
       +static size_t
        string_buffer_realloc(String *s, size_t newsz)
        {
       +        char *tmp;
                size_t allocsz;
        
                for (allocsz = 64; allocsz <= newsz; allocsz *= 2)
                        ;
       -        if (!(s->data = realloc(s->data, allocsz)))
       -                eprintf("realloc: %s\n", strerror(errno));
       -        s->bufsiz = alloclen;
       +        if (!(tmp = realloc(s->data, allocsz))) {
       +                weprintf("realloc: %s\n", strerror(errno));
       +        } else {
       +                s->data   = tmp;
       +                s->datasz = allocsz;
       +        }
       +
       +        return s->datasz;
        }
        
       -static void
       +static size_t
        string_append(String *s, const char *data, size_t len)
        {
       +        size_t newlen;
       +
                if (!len)
       -                return;
       +                return len;
       +
       +        newlen = s->len + len;
                /* check if allocation is necesary, don't shrink buffer,
                 * should be more than datasz ofcourse. */
       -        if (s->len + len >= s->datasz)
       -                string_buffer_realloc(s, s->len + len + 1);
       +        if (newlen >= s->datasz) {
       +                if (string_buffer_realloc(s, newlen + 1) <= newlen)
       +                        return 0;
       +        }
                memcpy(s->data + s->len, data, len);
       -        s->len += len;
       +        s->len = newlen;
                s->data[s->len] = '\0';
       +        return len;
        }
        
        void *
       -ecalloc(size_t nmemb, size_t size)
       +wecalloc(size_t nmemb, size_t size)
        {
                void *p;
        
                if (!(p = calloc(nmemb, size)))
       -                eprintf("calloc: %s\n", strerror(errno));
       +                weprintf("calloc: %s\n", strerror(errno));
        
                return p;
        }
        
        char *
       -estrndup(const char *s, size_t n)
       +westrndup(const char *s, size_t n)
        {
                char *p;
        
                if (!(p = strndup(s, n)))
       -                eprintf("strndup: %s\n", strerror(errno));
       +                weprintf("strndup: %s\n", strerror(errno));
                return p;
        }
        
        char *
       -estrdup(const char *s)
       +westrdup(const char *s)
        {
                char *p;
        
                if (!(p = strdup(s)))
       -                eprintf("strdup: %s\n", strerror(errno));
       +                weprintf("strdup: %s\n", strerror(errno));
        
                return p;
        }
       @@ -395,10 +394,10 @@ match(const char *pat, const char *str, int fcase)
        domain=...   if domain is prefixed with ~, ignore.
        multiple domains can be separated with |
        */
       -struct filterdomain *
       -parsedomains(char *s, int sep)
       +static int
       +parsedomains(char *s, int sep, struct filterdomain **head)
        {
       -        struct filterdomain *head = NULL, *d, *last = NULL;
       +        struct filterdomain *d, *last = *head = NULL;
                char *p;
                int inverse;
        
       @@ -414,12 +413,14 @@ parsedomains(char *s, int sep)
                        if ((p = strchr(s, sep))) /* TODO: should not contain , */
                                *p = '\0';
        
       -                d = ecalloc(1, sizeof(struct filterdomain));
       +                if (!(d = wecalloc(1, sizeof(struct filterdomain))))
       +                        return -1;
       +                if (!(d->domain = westrdup(s)))
       +                        return -1;
                        d->inverse = inverse;
       -                d->domain = estrdup(s);
        
       -                if (!head)
       -                        head = last = d;
       +                if (!*head)
       +                        *head = last = d;
                        else
                                last = last->next = d;
        
       @@ -429,10 +430,10 @@ parsedomains(char *s, int sep)
                        }
                } while (p);
        
       -        return head;
       +        return (*head != NULL);
        }
        
       -void
       +static int
        parsedomainselement(struct filterrule *f, char *s)
        {
                struct filterdomain *d, *last;
       @@ -440,14 +441,17 @@ parsedomainselement(struct filterrule *f, char *s)
                for (last = f->domains; last && last->next; last = last->next)
                        ;
        
       -        d = parsedomains(s, ',');
       +        if (parsedomains(s, ',', &d) < 0)
       +                return -1;
                if (last)
                        last->next = d;
                else
                        f->domains = d;
       +
       +        return (d != NULL);
        }
        
       -void
       +static int
        parsedomainsoption(struct filterrule *f, char *s)
        {
                struct filterdomain *d, *last;
       @@ -455,11 +459,14 @@ parsedomainsoption(struct filterrule *f, char *s)
                for (last = f->domains; last && last->next; last = last->next)
                        ;
        
       -        d = parsedomains(s, '|');
       +        if (parsedomains(s, '|', &d) < 0)
       +                return -1;
                if (last)
                        last->next = d;
                else
                        f->domains = d;
       +
       +        return (d != NULL);
        }
        
        int
       @@ -574,9 +581,11 @@ parserule(struct filterrule *f, char *s)
        
                if ((p = strstr(s, "#@#"))) {
                        *p = '\0';
       -                parsedomainselement(f, s);
       +                if (parsedomainselement(f, s) < 0)
       +                        return -1;
                        *p = '#';
       -                f->css = estrdup(p + 3);
       +                if (!(f->css = westrdup(p + 3)))
       +                        return -1;
                        f->isexception = 1;
                        goto end; /* end of CSS rule */
                }
       @@ -585,9 +594,11 @@ parserule(struct filterrule *f, char *s)
                "Simplified element hiding syntax" is not supported. */
                if ((p = strstr(s, "##"))) {
                        *p = '\0';
       -                parsedomainselement(f, s);
       +                if (parsedomainselement(f, s) < 0)
       +                        return -1;
                        *p = '#';
       -                f->css = estrdup(p + 2);
       +                if (!(f->css = westrdup(p + 2)))
       +                        return -1;
                        goto end; /* end of rule */
                }
        
       @@ -607,12 +618,14 @@ parserule(struct filterrule *f, char *s)
        
                /* no options, use rest of line as uri. */
                if (!(p = strrchr(s, '$'))) {
       -                f->uri = estrdup(s);
       +                if (!(f->uri = westrdup(s)))
       +                        return -1;
                        goto end;
                }
        
                /* has options */
       -        f->uri = estrndup(s, p - s);
       +        if (!(f->uri = westrndup(s, p - s)))
       +                return -1;
                s = ++p;
        
                /* blockmask, has options? default: allow all options, case-sensitive
       @@ -674,10 +687,11 @@ debugrule(struct filterrule *r)
        struct filterrule *
        loadrules(FILE *fp)
        {
       +        struct filterrule f, *r, *rn = NULL, *rules = NULL;
                char *line = NULL;
                size_t linesiz = 0;
                ssize_t n;
       -        struct filterrule f, *r, *rn = NULL, *rules = NULL;
       +        int ret;
        
                /* TODO: handle ferror() */
                /* load rules */
       @@ -687,13 +701,16 @@ loadrules(FILE *fp)
                        if (n > 0 && line[n - 1] == '\r')
                                line[--n] = '\0';
        
       -                if (parserule(&f, line)) {
       -                        r = ecalloc(1, sizeof(struct filterrule));
       +                if ((ret = parserule(&f, line) > 0)) {
       +                        if (!(r = wecalloc(1, sizeof(struct filterrule))))
       +                                return NULL;
                                if (!rules)
                                        rules = rn = r;
                                else
                                        rn = rn->next = r;
                                memcpy(rn, &f, sizeof(struct filterrule));
       +                } else if (ret < 0) {
       +                        return NULL;
                        }
                }
                return rules;
       @@ -704,7 +721,8 @@ newpage(WebKitWebPage *page)
        {
                Page *p;
        
       -        p = ecalloc(1, sizeof(Page));
       +        if (!(p = wecalloc(1, sizeof(Page))))
       +                return NULL;
                p->next = pages;
                pages = p;
        
       @@ -724,13 +742,15 @@ documentloaded(WebKitWebPage *wp, Page *p)
                struct filterrule *r;
                const char *uri = webkit_web_page_get_uri(p->webpage);
                char *domain;
       +        size_t len;
        
                if (!uri || (strncmp(uri, "http://", sizeof("http://") - 1) &&
                    strncmp(uri, "https://", sizeof("https://") - 1)))
                        return;
        
                domain = strstr(uri, "://") + sizeof("://") - 1;
       -        domain = estrndup(domain, strcspn(domain, "/"));
       +        if (!(domain = westrndup(domain, strcspn(domain, "/"))))
       +                return;
        
                printf("uri: %s\n", uri);
                printf("domain: %s\n", domain);
       @@ -741,8 +761,12 @@ documentloaded(WebKitWebPage *wp, Page *p)
                for (r = rules; r; r = r->next) {
                        if (!r->css || !r->domains || !matchrule(r, "", "", domain))
                                continue;
       -                string_append(&sitecss, r->css, strlen(r->css));
       -                string_append(&sitecss, STRP("{display:none;}"));
       +                len = strlen(r->css);
       +                if (string_append(&sitecss, r->css, len) < len)
       +                        return;
       +                len = sizeof("{display:none;}") -1;
       +                if (string_append(&sitecss, "{display:none;}", len) < len)
       +                        return;
                }
                printf("sitecss: %s\n", sitecss.data ? sitecss.data : "<empty>");
        #endif
       @@ -786,7 +810,8 @@ sendrequest(WebKitWebPage *wp, WebKitURIRequest *req,
                        return FALSE;
        
                domain = strstr(uri, "://") + sizeof("://") - 1;
       -        domain = estrndup(domain, strcspn(domain, "/"));
       +        if (!(domain = westrndup(domain, strcspn(domain, "/"))))
       +                return FALSE;
        
                /* match rules */
                for (r = rules; r; r = r->next) {
       @@ -809,12 +834,13 @@ sendrequest(WebKitWebPage *wp, WebKitURIRequest *req,
        static void
        webpagecreated(WebKitWebExtension *e, WebKitWebPage *p, gpointer unused)
        {
       -        Page *np = newpage(p);
       +        Page *np;
       +
       +        if (!(np = newpage(p)))
       +                return;
        
       -        g_signal_connect(p, "document-loaded",
       -                         G_CALLBACK(documentloaded), np);
       -        g_signal_connect(p, "send-request",
       -                         G_CALLBACK(sendrequest), np);
       +        g_signal_connect(p, "document-loaded", G_CALLBACK(documentloaded), np);
       +        g_signal_connect(p, "send-request", G_CALLBACK(sendrequest), np);
        }
        
        G_MODULE_EXPORT void
       @@ -823,6 +849,7 @@ webkit_web_extension_initialize(WebKitWebExtension *ext)
                struct filterrule *r;
                FILE *fp;
                char filepath[PATH_MAX], *e;
       +        size_t len;
                int n;
        
                if ((e = getenv("SURF_ADBLOCK_FILE"))) {
       @@ -840,12 +867,12 @@ webkit_web_extension_initialize(WebKitWebExtension *ext)
        
                if (!(fp = fopen(filepath, "r"))) {
                        weprintf("fatal: cannot open rules file %s: %s\n",
       -                        filepath, strerror(errno));
       +                         filepath, strerror(errno));
                        return;
                }
                if (!(rules = loadrules(fp))) {
                        weprintf("fatal: cannot read rules file %s: %s\n",
       -                        filepath, strerror(errno));
       +                         filepath, strerror(errno));
                        return;
                }
                fclose(fp);
       @@ -855,10 +882,13 @@ webkit_web_extension_initialize(WebKitWebExtension *ext)
                        if (!r->css || r->domains)
                                continue;
        
       -                string_append(&globalcss, r->css, strlen(r->css));
       -                string_append(&globalcss, STRP("{display:none;}"));
       +                len = strlen(r->css);
       +                if (string_append(&globalcss, r->css, strlen(r->css)) < len)
       +                        return;
       +                len = sizeof("{display:none;}") - 1;
       +                if (string_append(&globalcss, "{display:none;}", len) < len)
       +                        return;
                }
        
       -        g_signal_connect(ext, "page-created",
       -                         G_CALLBACK(webpagecreated), NULL);
       +        g_signal_connect(ext, "page-created", G_CALLBACK(webpagecreated), NULL);
        }