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