diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index bb79f658143de47521b294b575302194ee3d2632..6d2cfd838d517bb4763caa34cfdd2f8c32513fb9 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -679,6 +679,34 @@ static int get_prefix(char *text, int *bytes, int *len)
 	return(depth);
 }
 
+static void outbuf_append(char **outbuf, char **outp, char *append, int len, int *outlen)
+{
+	char	*p;
+
+	/* Terminate outbuf */
+	**outp=0;
+	/* Check if there's room */
+	if(*outp - *outbuf + len < *outlen) {
+		memcpy(*outp, append, len);
+		*outp+=len;
+		return;
+	}
+	/* Not enough room, double the size. */
+	*outlen *= 2;
+	p=realloc(*outbuf, *outlen);
+	if(p==NULL) {
+		/* Can't do it. */
+		*outlen/=2;
+		return;
+	}
+	/* Set outp for new buffer */
+	*outp=p+(*outp - *outbuf);
+	*outbuf=p;
+	memcpy(*outp, append, len);
+	*outp+=len;
+	return;
+}
+
 static JSBool
 js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
@@ -698,6 +726,7 @@ js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	int			prefix_bytes=0;
 	int			quote_count=0;
 	int			old_prefix_bytes=0;
+	int			outbuf_size=0;
 	JSString*	js_str;
 
 	if(JSVAL_IS_VOID(argv[0]))
@@ -706,7 +735,8 @@ js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL) 
 		return(JS_FALSE);
 
-	if((outbuf=(char*)malloc((strlen(inbuf)*3)+1))==NULL)
+	outbuf_size=strlen(inbuf)*3+1;
+	if((outbuf=(char*)malloc(outbuf_size))==NULL)
 		return(JS_FALSE);
 	outp=outbuf;
 
@@ -754,8 +784,7 @@ js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 				if(!inbuf[i+1]) {			/* EOF */
 					linebuf[l++]='\r';
 					linebuf[l++]='\n';
-					memcpy(outp, linebuf, l);
-					outp+=l;
+					outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
 					l=0;
 					ocol=1;
 				}
@@ -764,8 +793,7 @@ js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 					memcpy(prefix,inbuf+i+1-prefix_bytes,prefix_bytes);
 					linebuf[l++]='\r';
 					linebuf[l++]='\n';
-					memcpy(outp, linebuf, l);
-					outp+=l;
+					outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
 					strncpy(linebuf,prefix,prefix_bytes);
 					l=prefix_bytes;
 					ocol=prefix_len+1;
@@ -774,8 +802,7 @@ js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 				else if(isspace(inbuf[i+1])) {	/* Next line starts with whitespace.  This is a "hard" CR. */
 					linebuf[l++]='\r';
 					linebuf[l++]='\n';
-					memcpy(outp, linebuf, l);
-					outp+=l;
+					outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
 					l=0;
 					ocol=1;
 				}
@@ -786,8 +813,7 @@ js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 						if(icol+k+1 < oldlen) {	/* The next word would have fit but isn't here.  Must be a hard CR */
 							linebuf[l++]='\r';
 							linebuf[l++]='\n';
-							memcpy(outp, linebuf, l);
-							outp+=l;
+							outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
 							if(prefix)
 								strcpy(linebuf,prefix);
 							l=prefix_bytes;
@@ -865,20 +891,15 @@ js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 					/* Move to start of whitespace */
 					while(l>0 && isspace(l))
 						l--;
-					memcpy(outp, linebuf, l+1);
-					outp+=l+1;
-					*(outp++)='\r';
-					*(outp++)='\n';
+					outbuf_append(&outbuf, &outp, linebuf, l+1, &outbuf_size);
+					outbuf_append(&outbuf, &outp, "\r\n", 2, &outbuf_size);
 					/* Move trailing words to start of buffer. */
 					l=prefix_bytes;
 					if(k-t>0)							/* k-1 is the last char position.  t is the start of the next line position */
 						memmove(linebuf+l, linebuf+t, k-t);
-					if(prefix)
-						memcpy(linebuf,prefix,prefix_bytes);
-					ocol=prefix_len+1;
 					l+=k-t;
 					/* Find new ocol */
-					for(ocol=prefix_len+1,t=0; t<l; t++) {
+					for(ocol=prefix_len+1,t=prefix_bytes; t<l; t++) {
 						switch(linebuf[t]) {
 							case '\x01':	/* CTRL-A */
 								if(linebuf[t+1]!='\x01')
@@ -896,8 +917,7 @@ js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	if(l) {
 		linebuf[l++]='\r';
 		linebuf[l++]='\n';
-		memcpy(outp, linebuf, l);
-		outp+=l;
+		outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
 	}
 	*outp=0;
 	/* If there were no CRs in the input, strip all CRs */