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); }