ref: 00712034efcc8c962638d2ab0d2cd98e93d04aa5
parent: b145798881615106aea2f196cf69c32984c11a1c
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Wed Sep 4 17:27:15 EDT 2013
libhtml: fix memory leaks
--- a/sys/src/libhtml/build.c
+++ b/sys/src/libhtml/build.c
@@ -693,10 +693,16 @@
bg = makebackground(nil, acolorval(tok, Abgcolor, di->background.color));
bgurl = aurlval(tok, Abackground, nil, di->base);
if(bgurl != nil) {- if(di->backgrounditem != nil)
- freeitem((Item*)di->backgrounditem);
- // really should remove old item from di->images list,
- // but there should only be one BODY element ...
+ if(di->backgrounditem != nil){+ Iimage **ii;
+ for(ii=&di->images; *ii != nil; ii = &((*ii)->nextimage)){+ if(*ii == di->backgrounditem){+ *ii = di->backgrounditem->nextimage;
+ break;
+ }
+ }
+ freeitem(di->backgrounditem);
+ }
di->backgrounditem = (Iimage*)newiimage(bgurl, nil, ALnone, 0, 0, 0, 0, 0, 0, nil);
di->backgrounditem->nextimage = di->images;
di->images = di->backgrounditem;
@@ -747,8 +753,11 @@
fprint(2, "warning: unexpected </CAPTION>\n");
continue;
}
+ if(curtab->caption != nil)
+ freeitems(curtab->caption);
curtab->caption = ps->items->next;
- free(ps);
+ ps->items->next = nil;
+ freepstate(ps);
ps = nextps;
break;
@@ -1694,6 +1703,7 @@
fprint(2, "warning: empty row\n");
curtab->rows = tr->next;
tr->next = nil;
+ free(tr);
}
else
tr->flags = 0;
@@ -1803,6 +1813,7 @@
// note: ans may be nil and di->kids not nil, if there's a frameset!
outerps->items = newispacer(ISPnull);
outerps->lastit = outerps->items;
+ outerps->prelastit = nil;
is->psstk = ps;
if(ans != nil && di->hasscripts) {// TODO evalscript(nil);
@@ -1817,6 +1828,7 @@
else
printitems(ans, "getitems returning:");
}
+ _freetokens(toks, tokslen);
return ans;
}
@@ -1892,7 +1904,10 @@
fprint(2, "warning: parse state stack is wrong\n");
}
else {+ if(c->content != nil)
+ freeitems(c->content);
c->content = psstk->items->next;
+ psstk->items->next = nil;
c->flags &= ~TFparsing;
freepstate(psstk);
psstk = psstknext;
@@ -1977,6 +1992,7 @@
if(ps->skipping) {if(warn)
fprint(2, "warning: skipping item: %I\n", it);
+ freeitem(it);
return;
}
it->anchorid = ps->curanchor;
@@ -2213,6 +2229,7 @@
// try to avoid making empty items
// but not crucial f the occasional one gets through
if(nl == 0 && ps->prelastit != nil) {+ freeitems(ps->lastit);
ps->lastit = ps->prelastit;
ps->lastit->next = nil;
ps->prelastit = nil;
@@ -2474,6 +2491,7 @@
// copy the data from the allocated Tablerow into the array slot
t->rows[r] = *row;
rownext = row->next;
+ free(row);
row = &t->rows[r];
r--;
rcols = 0;
@@ -2482,7 +2500,7 @@
// If rowspan is > 1 but this is the last row,
// reset the rowspan
if(c != nil && c->rowspan > 1 && r == nrow-2)
- c->rowspan = 1;
+ c->rowspan = 1;
// reverse row->cells list (along nextinrow pointers)
row->cells = nil;
@@ -3220,6 +3238,7 @@
free(ga->style);
free(ga->title);
freescriptevents(ga->events);
+ free(ga);
}
free(it);
}
@@ -3250,6 +3269,7 @@
free(ff->name);
free(ff->value);
+ freeitem(ff->image);
for(o = ff->options; o != nil; o = onext) {onext = o->next;
free(o->value);
@@ -3273,6 +3293,7 @@
for(c = t->cells; c != nil; c = cnext) {cnext = c->next;
freeitems(c->content);
+ free(c);
}
if(t->grid != nil) {for(i = 0; i < t->nrow; i++)
@@ -3428,7 +3449,8 @@
return;
free(d->src);
free(d->base);
- freeitem((Item*)d->backgrounditem);
+ free(d->doctitle);
+ freeitem(d->backgrounditem);
free(d->refresh);
freekidinfos(d->kidinfo);
freeanchors(d->anchors);
@@ -3440,11 +3462,10 @@
free(d);
}
-// Currently, someone else owns all the memory
-// pointed to by things in a Pstate.
static void
freepstate(Pstate* p)
{+ freeitems(p->items);
free(p);
}
@@ -3456,7 +3477,7 @@
for(p = pshead; p != nil; p = pnext) {pnext = p->next;
- free(p);
+ freepstate(p);
}
}
--- a/sys/src/libhtml/lex.c
+++ b/sys/src/libhtml/lex.c
@@ -611,6 +611,7 @@
a = 0;
if(ts->mtype == TextHtml) { for(;;) {+ assert(ai <= alen);
if(alen - ai < ToksChunk/32) {alen += ToksChunk;
a = erealloc(a, alen*sizeof *a);
@@ -639,6 +640,7 @@
else {// plain text (non-html) tokens
for(;;) {+ assert(ai <= alen);
if(alen - ai < ToksChunk/32) {alen += ToksChunk;
a = erealloc(a, alen*sizeof *a);
@@ -732,6 +734,7 @@
memcpy(&s[i], buf, j*sizeof *s);
s[i+j] = 0;
}
+ setmalloctag(s, getcallerpc(&s));
return s;
}
@@ -900,6 +903,7 @@
Token* tok;
Rune buf[BIGBUFSIZE];
+ al = nil;
rbra = 0;
nexti = ts->i;
tok = &a[*pai];
@@ -948,7 +952,6 @@
else
tok->text = _Strndup(buf, i); // for warning print, in build
// attribute gathering loop
- al = nil;
while(1) {// look for "ws name" or "ws name ws = ws val" (ws=whitespace)
// skip whitespace
@@ -1113,6 +1116,7 @@
if(warn)
fprint(2, "warning: incomplete tag at end of page\n");
backup(ts, nexti);
+ freeattrs(al);
tok->tag = Data;
tok->text = _Strdup(L"<");
return Data;
@@ -1462,6 +1466,7 @@
ans->attid = attid;
ans->value = value;
ans->next = link;
+ setmalloctag(ans, getcallerpc(&attid));
return ans;
}
--- a/sys/src/libhtml/utils.c
+++ b/sys/src/libhtml/utils.c
@@ -328,9 +328,12 @@
Rune*
_Strdup(Rune* s)
{+ Rune* ans;
if(s == nil)
return nil;
- return _Strndup(s, runestrlen(s));
+ ans = _Strndup(s, runestrlen(s));
+ setmalloctag(ans, getcallerpc(&s));
+ return ans;
}
// emalloc and copy n chars of s (assume s is at least that long),
@@ -346,6 +349,7 @@
ans = _newstr(n);
memmove(ans, s, n*sizeof(Rune));
ans[n] = 0;
+ setmalloctag(ans, getcallerpc(&s));
return ans;
}
// emalloc enough room for n Runes, plus 1 null terminator.
@@ -353,7 +357,11 @@
Rune*
_newstr(int n)
{- return (Rune*)emalloc((n+1)*sizeof(Rune));
+ Rune* ans;
+
+ ans = (Rune*)emalloc((n+1)*sizeof(Rune));
+ setmalloctag(ans, getcallerpc(&n));
+ return ans;
}
// emalloc and copy s+t
@@ -372,6 +380,7 @@
p = _Stradd(ans, s, ns);
p = _Stradd(p, t, nt);
*p = 0;
+ setmalloctag(ans, getcallerpc(&s));
return ans;
}
@@ -384,6 +393,7 @@
if(start == stop)
return nil;
t = _Strndup(s+start, stop-start);
+ setmalloctag(t, getcallerpc(&s));
return t;
}
@@ -530,6 +540,7 @@
ans = nil;
assert(0);
}
+ setmalloctag(ans, getcallerpc(&buf));
return ans;
}
@@ -575,6 +586,6 @@
default:
assert(0);
}
+ setmalloctag(ans, getcallerpc(&buf));
return ans;
-
}
--
⑨