code: 9ferno

Download patch

ref: 76acae031bbc63582596374842056452c6062772
parent: bc67178c247505d72696611797c6a3879dce84fd
author: 9ferno <gophone2015@gmail.com>
date: Wed Dec 29 06:31:03 EST 2021

fixed stack leak in forth bindings

--- a/libinterp/load.c
+++ b/libinterp/load.c
@@ -4,7 +4,7 @@
 #include "raise.h"
 #include <kernel.h>
 
-#define DP if(1){}else print
+#define DP if(0){}else print
 #define DNP if(1){}else print
 #define	A(r)	*((Array**)(r))
 
@@ -136,22 +136,22 @@
 	int c;
 
 	USED(offset);
-	DP("\tstring\t@mp+%zd=0x%p,len %d at 0x%p:\"", offset, absoluteoffset, len, stored);
+	DNP("\tstring\t@mp+%zd=0x%p,len %d at 0x%p:\"", offset, absoluteoffset, len, stored);
 	se = s + len;
 	for(; s < se; s++){
 		c = *s;
 		if(c == '\n')
-			DP("\\n");
+			DNP("\\n");
 		else if(c == '\0')
-			DP("\\z");
+			DNP("\\z");
 		else if(c == '"')
-			DP("\\\"");
+			DNP("\\\"");
 		else if(c == '\\')
-			DP("\\\\");
+			DNP("\\\\");
 		else
-			DP("%c", c);
+			DNP("%c", c);
 	}
-	DP("\"\n");
+	DNP("\"\n");
 }
 
 Module*
@@ -171,7 +171,7 @@
 	Link *l;
 	intptr i, n, v, pc, entry, entryt;
 
-	DP("\tsource\t\"%s\"\n", path);
+	DNP("\tsource\t\"%s\"\n", path);
 	istream = code;
 	isp = &istream;
 
@@ -225,7 +225,7 @@
 		goto bad;
 	}
 
-	DP("parsemod before instructions isize %d dsize %d hsize %d"
+	DNP("parsemod before instructions isize %d dsize %d hsize %d"
 		" lsize %d entry 0x%zx entryt 0x%zx sizeof(Inst) %d\n",
 		isize, dsize, hsize, lsize, entry, entryt, sizeof(Inst));
 	m->nprog = isize;
@@ -281,12 +281,12 @@
 			break;
 		}
 		if(i % 10 == 0)
-			DP("#%p\n", ip);
-		DP("	%d %zd %D\n", i, (intptr)ip, ip);
+			DNP("#%p\n", ip);
+		DNP("	%d %zd %D\n", i, (intptr)ip, ip);
 		ip++;		
 	}
 
-	DP("\tentry\t0,%d\n",hsize);
+	DNP("\tentry\t0,%d\n",hsize);
 	m->ntype = hsize;
 	m->type = malloc(hsize*sizeof(Type*));
 	if(m->type == nil) {
@@ -310,11 +310,11 @@
 			kwerrstr(exNomem);
 			goto bad;
 		}
-		DP("\tdesc\t$%d 0x%p has 0x%p of size %d nptrs %d:\"",
+		DNP("\tdesc\t$%d 0x%p has 0x%p of size %d nptrs %d:\"",
 			id, m->type+id, pt, tsz, tnp);
 		for(e = istream; e < istream+tnp; e++)
-			DP("%.2x", *e);
-		DP("\"\n");
+			DNP("%.2x", *e);
+		DNP("\"\n");
 		istream += tnp;
 		m->type[id] = pt;
 	}
@@ -327,12 +327,12 @@
 		}
 		h = heapz(pt);
 		m->origmp = H2D(uchar*, h);
-		DP("\tm->origmp 0x%p belongs to heap at 0x%p, uses type at 0x%p\n",
+		DNP("\tm->origmp 0x%p belongs to heap at 0x%p, uses type at 0x%p\n",
 			m->origmp, h, pt);
 	}
 	addr = m->origmp;
 	dasp = 0;
-	DP("\tvar\t@mp, size %d\n", dsize);
+	DNP("\tvar\t@mp, size %d\n", dsize);
 	for(;;) {
 		sm = *istream++;
 		if(sm == 0)
@@ -353,62 +353,62 @@
 			*(String**)si = s;
 			break;
 		case DEFB:
-			DP("\tbyte\t@mp+%d", v);
+			DNP("\tbyte\t@mp+%d", v);
 			for(i = 0; i < n; i++){
-				DP(",%d", *istream & 0xff);
+				DNP(",%d", *istream & 0xff);
 				*si++ = *istream++;
 			}
-			DP(" n=%d\n", n);
+			DNP(" n=%d\n", n);
 			break;
 		case DEFW:
-			DP("\tword\t@mp+%d len %d:", v, n);
+			DNP("\tword\t@mp+%d len %d:", v, n);
 			for(i = 0; i < n; i++) {
 				*(WORD*)si = disw(isp);
-				DP(" 0x%zx", *(WORD*)si);
+				DNP(" 0x%zx", *(WORD*)si);
 				si += sizeof(WORD);
 			}
-			DP("\n");
+			DNP("\n");
 			break;
 		case DEFL:
-			DP("\tlong\t@mp+%d", v);
+			DNP("\tlong\t@mp+%d", v);
 			for(i = 0; i < n; i++) {
 				hi = disw(isp);
 				lo = disw(isp);
 				*(LONG*)si = (LONG)hi << 32 | (LONG)(u32)lo;
-				DP(",%lld 0x%zx", *(LONG*)si, *(LONG*)si);
+				DNP(",%lld 0x%zx", *(LONG*)si, *(LONG*)si);
 				si += sizeof(LONG);
 			}
-			DP("\n");
+			DNP("\n");
 			break;
 		case DEFF:
-			DP("\treal\t@mp+%d", v);
+			DNP("\treal\t@mp+%d", v);
 			for(i = 0; i < n; i++) {
-				DP(" raw: ");
+				DNP(" raw: ");
 				for(int j = 0; j<8; j++){
-					DP(" 0x%x", ((u8*)isp)[j]);
+					DNP(" 0x%x", ((u8*)isp)[j]);
 				}
 				ul[0] = disw(isp);
 				ul[1] = disw(isp);
 				/*print("canontod ul[0] 0x%x ul[1] 0x%x ", ul[0], ul[1]);*/
 				*(REAL*)si = canontod(ul);
-				/*DP("__");
-				DP(",%g", *(REAL*)si);
-				DP("--");*/
+				/*DNP("__");
+				DNP(",%g", *(REAL*)si);
+				DNP("--");*/
 				si += sizeof(REAL);
 			}
-			DP("\n");
+			DNP("\n");
 			break;
 		case DEFA:			/* Array */
-			DP("\tarray\t@mp+%d", v);
+			DNP("\tarray\t@mp+%d", v);
 			v = disw(isp);
 			if(v < 0 || v > m->ntype) {
 				kwerrstr("bad array type");
 				goto bad;
 			}
-			DP(",$%d", v);
+			DNP(",$%d", v);
 			pt = m->type[v];
 			v = disw(isp);
-			DP(",%d", v);
+			DNP(",%d", v);
 			h = nheap(sizeof(Array)+(pt->size*v));
 			h->t = &Tarray;
 			h->t->ref++;
@@ -421,9 +421,9 @@
 			for(i=(intptr)ary->data;
 				i < v;
 				i++){
-				DP(",%d",*(uchar*)(i+ary));
+				DNP(",%d",*(uchar*)(i+ary));
 			}
-			DP("\n");
+			DNP("\n");
 			initarray(pt, ary);
 			A(si) = ary;
 			break;			
@@ -433,7 +433,7 @@
 				kwerrstr("ind not array");
 				goto bad;
 			}
-			DP("\tindir\t@mp+%d", v);
+			DNP("\tindir\t@mp+%d", v);
 			v = disw(isp);
 			if(v > ary->len || v < 0 || dasp >= DADEPTH) {
 				kwerrstr("array init range");
@@ -441,7 +441,7 @@
 			}
 			dastack[dasp++] = addr;
 			addr = ary->data+v*ary->t->size;
-			DP(",%d,%zd 0x%zx\n",
+			DNP(",%d,%zd 0x%zx\n",
 				v, (intptr)ary->data+v*ary->t->size,
 				(intptr)ary->data+v*ary->t->size);
 			break;
@@ -450,14 +450,14 @@
 				kwerrstr("pop range");
 				goto bad;
 			}
-			DP("\tapop\n");
+			DNP("\tapop\n");
 			addr = dastack[--dasp];
 			break;
 		}
 	}
-	/*DP("		Initialized origmp\n");
+	/*DNP("		Initialized origmp\n");
 	for(int i = 0; i < m->type[0]->size/(sizeof(intptr)); i++){
-		DP("\t\t0x%p\t%zx\n", (intptr*)m->origmp+i, *((intptr*) m->origmp+i));
+		DNP("\t\t0x%p\t%zx\n", (intptr*)m->origmp+i, *((intptr*) m->origmp+i));
 	}*/
 	mod = istream;
 	if(memchr(mod, 0, 128) == 0) {
@@ -469,7 +469,7 @@
 		kwerrstr(exNomem);
 		goto bad;
 	}
-	DP("\tmodule\t%s\n", m->name);
+	DNP("\tmodule\t%s\n", m->name);
 	while(*istream++)
 		;
 
@@ -487,18 +487,18 @@
 			pt = m->type[de];
 		mlink(m, l, istream, v, pc, pt);
 		if(de != -1){
-			DP("\tlink\tidx %d, type %d size %d np %d ",
+			DNP("\tlink\tidx %d, type %d size %d np %d ",
 				i, de, pt->size, pt->np);
 			if(pt->np > 0){
-				DP("map");
+				DNP("map");
 				for(b = pt->map; b < pt->map+pt->np; b++)
-					DP(" %.2x", *b);
-				DP(" ");
+					DNP(" %.2x", *b);
+				DNP(" ");
 			}
-			DP(", pc %zd, sig 0x%ux,\"%s\"\n",
+			DNP(", pc %zd, sig 0x%ux,\"%s\"\n",
 				pc, v, (char*)istream);
 		}else
-			DP("\tlink\tidx %d type %d, pc %zd, sig 0x%ux,\"%s\"\n",
+			DNP("\tlink\tidx %d type %d, pc %zd, sig 0x%ux,\"%s\"\n",
 				i, de, pc, v, (char*)istream);
 		while(*istream++)
 			;
@@ -520,10 +520,10 @@
 			kwerrstr(exNomem);
 			goto bad;
 		}
-		DP("\tldts\t@ldt,%d\n", nl);
+		DNP("\tldts\t@ldt,%d\n", nl);
 		for(i = 0; i < nl; i++, i2++){
 			n = operand(isp);
-			DP("\text\t@ldts+%d,%d,%zd\n",
+			DNP("\text\t@ldts+%d,%d,%zd\n",
 				i, n, (intptr)i2-(intptr)m->ldt);
 			i1 = *i2 = (Import*)malloc((n+1)*sizeof(Import));
 			if(i1 == nil){
@@ -537,7 +537,7 @@
 					kwerrstr(exNomem);
 					goto bad;
 				}
-				DP("\text\t@ldt+%zd,idx %d, sig 0x%ux,\"%s\"\n",
+				DNP("\text\t@ldt+%zd,idx %d, sig 0x%ux,\"%s\"\n",
 					(intptr)i1-(intptr)m->ldt,
 					j, i1->sig, (char*)istream);
 				while(*istream++)
@@ -558,7 +558,7 @@
 			kwerrstr(exNomem);
 			goto bad;
 		}
-		DP("\texceptions\t%d\n", nh);
+		DNP("\texceptions\t%d\n", nh);
 		h = m->htab;
 		for(i = 0; i < nh; i++, h++){
 			h->eoff = operand(isp);
@@ -576,7 +576,7 @@
 				goto bad;
 			}
 			e = h->etab;
-			DP("\texception\t%d: offset %zd pc1 %zd pc2 %zd"
+			DNP("\texception\t%d: offset %zd pc1 %zd pc2 %zd"
 				" desc %d nlab %d ne %zd\n",
 				i, h->eoff, h->pc1, h->pc2,
 				descid, n, h->ne);
@@ -589,11 +589,11 @@
 				while(*istream++)
 					;
 				e->pc = operand(isp);
-				DP("\texctab\t\"%s\", %zd\n", e->s, e->pc);
+				DNP("\texctab\t\"%s\", %zd\n", e->s, e->pc);
 			}
 			e->s = nil;
 			e->pc = operand(isp);
-			DP("\texctab\t*, %zd\n", e->pc);
+			DNP("\texctab\t*, %zd\n", e->pc);
 		}
 		istream++;
 	}
@@ -622,7 +622,7 @@
 		kwerrstr(exNomem);
 		goto bad;
 	}
-	DP("\tsource\t\"%s\"\n", m->path);
+	DNP("\tsource\t\"%s\"\n", m->path);
 	m->link = modules;
 	modules = m;
 
--- a/os/pc64/bindings.s
+++ b/os/pc64/bindings.s
@@ -97,6 +97,7 @@
 	CALL kopen(SB)
 	MOVQ 16(SP), UP
 	C_TO_F_1
+	ADDQ $24, SP
 	NEXT
 
 TEXT	fthclose(SB), 1, $16	/* ( fd -- n ) */
@@ -105,6 +106,7 @@
 	CALL kclose(SB)
 	MOVQ 24(SP), UP
 	C_TO_F_1
+	ADDQ $16, SP
 	NEXT
 
 TEXT	fthread(SB), 1, $32	/* ( n a fd -- n2 ) */
@@ -121,6 +123,7 @@
 	CALL kread(SB)
 	MOVQ 24(SP), UP
 	C_TO_F_1
+	ADDQ $32, SP
 	NEXT
 
 /* no link register in amd64
@@ -142,6 +145,7 @@
 	CALL kwrite(SB)
 	MOVQ 24(SP), UP
 	C_TO_F_1
+	ADDQ $32, SP
 	NEXT
 
 TEXT	fthseek(SB), 1, $32	/* ( type pos fd -- n ) */
@@ -150,4 +154,5 @@
 	CALL kseek(SB)
 	MOVQ 24(SP), UP
 	C_TO_F_1
+	ADDQ $32, SP
 	NEXT
--- a/os/pc64/trap.c
+++ b/os/pc64/trap.c
@@ -124,12 +124,15 @@
 }
 
 void
-dumprstack(intptr h, intptr rsp)
+dumprstack(intptr h, intptr rsp, intptr he)
 {
 	intptr i;
 	int l=0;
 
-	print("Forth return stack RSTACK 0x%zx\n", h+RSTACK);
+	print("Forth return stack h 0x%zx rsp 0x%zx RSTACK 0x%zx he 0x%zx\n",
+			h, rsp, h+RSTACK, he);
+	if(he == 0 || h == 0 || rsp < h || rsp >= he || h+RSTACK < h || h+RSTACK >= he)
+		return;
 	for(i = h + RSTACK-8; i >= rsp; i-=8){
 		print("	0x%zx: 0x%zx", i, *(intptr*)i);
 		l++;
@@ -142,12 +145,15 @@
 }
 
 void
-dumppstack(intptr h, intptr psp)
+dumppstack(intptr h, intptr psp, intptr he)
 {
 	intptr i;
 	int l=0;
 
-	print("Forth parameter stack PSTACK 0x%zx\n", h+PSTACK);
+	print("Forth parameter stack h 0x%zx psp 0x%zx PSTACK 0x%zx he 0x%zx\n",
+			h, psp, h+PSTACK, he);
+	if(he == 0 || h == 0 || psp < h || psp >= he || h+PSTACK < h || h+PSTACK >= he)
+		return;
 	for(i = h + PSTACK-8; i >= psp; i-=8){
 		print("	0x%zx: 0x%zx", i, *(intptr*)i);
 		l++;
@@ -260,8 +266,9 @@
 		}
 		dumpregs(ureg);
 		if(vno < nelem(excname)){
-			dumprstack(ureg->r11, ureg->r8);
-			dumppstack(ureg->r11, ureg->dx);
+			dumprstack(ureg->r11, ureg->r8, ureg->r12);
+			dumppstack(ureg->r11, ureg->dx, ureg->r12);
+			_dumpstack(ureg);
 			panic("%s", excname[vno]);
 		}
 		panic("unknown trap/intr: %d\n", vno);
@@ -299,6 +306,8 @@
 			"  R11 UP %8.8zux  R12 UPE %8.8zux  R13 %8.8zux\n",
 		ureg->r8, ureg->r9, ureg->r10,
 		ureg->r11, ureg->r12, ureg->r13);
+	print("  R14 up %8.8zux  R15 m %8.8zux\n",
+		ureg->r14, ureg->r15);
 }
 
 void
@@ -362,13 +371,20 @@
 	i = 0;
 	if(up &&
 		(uintptr)&l >= (uintptr)up->kstack &&
-		(uintptr)&l <= (uintptr)up->kstack+KSTACK)
+		(uintptr)&l <= (uintptr)up->kstack+KSTACK){
 		estack = (uintptr)up->kstack+KSTACK;
-	else if((uintptr)&l >= (uintptr)m->stack &&
-		(uintptr)&l <= (uintptr)m+BY2PG)
+		print("up->kstack 0x%zux estack 0x%zux\n",(uintptr)up->kstack, estack);
+	}else if((uintptr)&l >= (uintptr)m->stack &&
+		(uintptr)&l <= (uintptr)m+BY2PG){
 		estack = (uintptr)m+MACHSIZE;
-	else
+		print("m->stack 0x%zux estack 0x%zux\n",(uintptr)m->stack, estack);
+	}else{
+		if(up)
+			print("up->kstack 0x%zux\n", (uintptr)up->kstack);
+		else
+			print("m->stack 0x%zux\n", (uintptr)m->stack);
 		return;
+	}
 
 	for(l=(uintptr)&l; l<estack; l+=sizeof(intptr)){
 		v = *(uintptr*)l;
@@ -447,8 +463,8 @@
 			read ? "read" : "write", ureg->pc, addr);
 print(buf);
 	dumpregs(ureg);
-	dumprstack(ureg->r11, ureg->r8);
-	dumppstack(ureg->r11, ureg->dx);
+	dumprstack(ureg->r11, ureg->r8, ureg->r12);
+	dumppstack(ureg->r11, ureg->dx, ureg->r12);
 dumpstack();
 	if(up->type == Interp)
 		disfault(ureg, buf);
--- a/os/port/allocb.c
+++ b/os/port/allocb.c
@@ -14,7 +14,7 @@
 struct
 {
 	Lock;
-	u32	bytes;
+	uintptr	bytes;
 } ialloc;
 
 /*
@@ -50,6 +50,17 @@
 	return b;
 }
 
+/* TODO Add Bhdr attributes here */
+void
+showblockheader(Block *b, intptr pc, char *str)
+{
+	iprint("%s called by 0x%8.8luX, pid %d base 0x%8.8luX lim 0x%8.8luX\n"
+			"	next 0x%8.8luX rp 0x%8.8luX wp 0x%8.8luX malloctag 0x%8.8luX\n",
+			str, pc, up->pid,
+			b->base, b->lim, b->next,
+			b->rp, b->wp, getmalloctag(b));
+}
+
 Block*
 allocb(int size)
 {
@@ -61,6 +72,7 @@
 	if(b == 0)
 		exhausted("Blocks");
 	setmalloctag(b, getcallerpc(&size));
+	/* showblockheader(b, getcallerpc(&size), "allocb()"); */
 	return b;
 }
 
@@ -92,6 +104,7 @@
 	return b;
 }
 
+void checkbl(Block *b, char *msg, intptr pc);
 void
 freeb(Block *b)
 {
@@ -105,6 +118,8 @@
 	 * pool of uncached buffers and provide their own free routine.
 	 */
 	if(b->free) {
+		/* checkbl(b, "checking block before free'ing\n", getcallerpc(&b));
+		print("freeb b 0x%zx b->free 0x%zx\n", b, (intptr)b->free); */
 		b->free(b);
 		return;
 	}
@@ -124,6 +139,36 @@
 	free(b);
 }
 
+/* same as checkb but with more details for debugging */
+void
+checkbl(Block *b, char *msg, intptr pc)
+{
+	void *dead = (void*)Bdead;
+
+	if(b == dead)
+		panic("checkb b %s %lux", msg, b);
+	if(b->base == dead || b->lim == dead || b->next == dead
+	  || b->rp == dead || b->wp == dead){
+		showblockheader(b, pc, "freeb() dead");
+		panic("checkb dead: %s\n", msg);
+	}
+
+	if(b->base > b->lim){
+		showblockheader(b, pc, "freeb() 0");
+		panic("checkb 0 %s %lux %lux", msg, b->base, b->lim);
+	}
+	if(b->rp < b->base){
+		showblockheader(b, pc, "freeb() 1");
+		panic("checkb 1 %s %lux %lux", msg, b->base, b->rp);
+	}
+	if(b->wp < b->base)
+		panic("checkb 2 %s %lux %lux", msg, b->base, b->wp);
+	if(b->rp > b->lim)
+		panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim);
+	if(b->wp > b->lim)
+		panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim);
+
+}
 void
 checkb(Block *b, char *msg)
 {
--- a/os/port/chan.c
+++ b/os/port/chan.c
@@ -530,11 +530,8 @@
 void
 cclose(Chan *c)
 {
-	if(c == nil || c->ref < 1 || c->flag&CFREE){
-		print("cclose before panic\n");
-		panic("cclose %#p c->path %s c->ref %d c->flag 0x%ux",
-				getcallerpc(&c), chanpath(c), c->ref, c->flag);
-	}
+	if(c == nil || c->ref < 1 || c->flag&CFREE)
+		panic("cclose %#p", getcallerpc(&c));
 
 	if(decref(c))
 		return;
--- a/os/port/devforth.c
+++ b/os/port/devforth.c
@@ -91,8 +91,8 @@
 	Fentry *f;
 	u8 *h, *dtop, *vh;
 	int n;
+	Bhdr *b;
 
-debug = 0;
 	h = fmem+DICTIONARY;
 	dtop = nil;
 	vh = fmem+WORDBEND+8;
@@ -99,11 +99,13 @@
 	print("loadforthdictionary fmem 0x%zx h 0x%zx dtop 0x%zx vh 0x%zx\n"
 			"	(intptr*)(fmem + DTOP) 0x%zx *(intptr*)(fmem + DTOP) 0x%zx\n"
 			"	RSTACK 0x%zx (intptr*)(fmem + RSTACK) 0x%zx\n"
-			"	PSTACK 0x%zx (intptr*)(fmem + PSTACK) 0x%zx\n",
+			"	PSTACK 0x%zx (intptr*)(fmem + PSTACK) 0x%zx\n"
+			"	FORTHEND 0x%zx (intptr*)(fmem + FORTHEND) 0x%zx\n",
 			fmem, (intptr)h, (intptr)dtop, (intptr)vh,
 			(intptr*)(fmem + DTOP), *(intptr*)(fmem + DTOP),
 			RSTACK, (intptr*)(fmem + RSTACK),
-			PSTACK, (intptr*)(fmem + PSTACK));
+			PSTACK, (intptr*)(fmem + PSTACK),
+			FORTHEND, (intptr*)(fmem + FORTHEND));
 	for(i=0; i < nelem(fentries); i++){
 		f = &fentries[i];
 		if(f->type == Header){
@@ -172,7 +174,19 @@
 	*(intptr*)(fmem + HERE) = (intptr)h;
 	*(intptr*)(fmem + DTOP) = (intptr)dtop;
 	*(intptr*)(fmem + VHERE) = (intptr)vh;
-debug = 0;
+	print("loadforthdictionary fmem 0x%zx h 0x%zx dtop 0x%zx vh 0x%zx\n"
+			"	(intptr*)(fmem + DTOP) 0x%zx *(intptr*)(fmem + DTOP) 0x%zx\n"
+			"	RSTACK 0x%zx (intptr*)(fmem + RSTACK) 0x%zx\n"
+			"	PSTACK 0x%zx (intptr*)(fmem + PSTACK) 0x%zx\n"
+			"	FORTHEND 0x%zx (intptr*)(fmem + FORTHEND) 0x%zx\n",
+			fmem, (intptr)h, (intptr)dtop, (intptr)vh,
+			(intptr*)(fmem + DTOP), *(intptr*)(fmem + DTOP),
+			RSTACK, (intptr*)(fmem + RSTACK),
+			PSTACK, (intptr*)(fmem + PSTACK),
+			FORTHEND, (intptr*)(fmem + FORTHEND));
+	b = D2B(b,fmem);
+	print("Bhdr b 0x%p b->magic 0x%x b->size %zd b->allocpc 0x%zx\n",
+			b, b->magic, b->size, b->allocpc);
 }
 
 extern intptr forthmain(u8 *);
@@ -296,7 +310,7 @@
 	p->kp = 0;
 
 	/* TODO align fmem to a page boundary */
-	p->fmem = malloc(FORTHHEAPSIZE);
+	p->fmem = mallocalign(FORTHHEAPSIZE, BY2PG, 0, 0);
 	if(p->fmem == nil)
 		panic("newforthproc p->fmem == nil\n");