From 7ff471f7d145359899a173af34d201a0816108b2 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Sat, 21 Jan 2006 01:33:32 +0000
Subject: [PATCH] Use xp_printf module for all JS printf/sprintf/fprintf
 methods: * eliminates segfaults/AVs on incorrect usage * auto-converts
 arguments to correct format type * eliminates portability problems with
 non-x86 platforms Hurrah for Deuce!

---
 src/sbbs3/js_file.c    | 33 +++---------------
 src/sbbs3/js_global.c  | 77 +++---------------------------------------
 src/sbbs3/js_sprintf.c | 67 ++++++++++++++++++++++++++++++++++++
 src/sbbs3/jsexec.c     | 31 +++--------------
 src/sbbs3/main.cpp     | 27 ++-------------
 src/sbbs3/objects.mk   |  1 +
 src/sbbs3/sbbs.h       |  5 ++-
 7 files changed, 88 insertions(+), 153 deletions(-)
 create mode 100644 src/sbbs3/js_sprintf.c

diff --git a/src/sbbs3/js_file.c b/src/sbbs3/js_file.c
index c7028fc2c9..7efe86c340 100644
--- a/src/sbbs3/js_file.c
+++ b/src/sbbs3/js_file.c
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -1297,10 +1297,6 @@ static JSBool
 js_fprintf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 	char*		cp;
-    uintN		i;
-	JSString *	fmt;
-    JSString *	str;
-	va_list		arglist[64];
 	private_t*	p;
 
 	*rval = JSVAL_FALSE;
@@ -1313,34 +1309,13 @@ js_fprintf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	if(p->fp==NULL)
 		return(JS_TRUE);
 
-	if((fmt=JS_ValueToString(cx, argv[0]))==NULL) {
-		JS_ReportError(cx,"JS_ValueToString failed");
-		return(JS_FALSE);
-	}
-
-	memset(arglist,0,sizeof(arglist));	/* Initialize arglist to NULLs */
-
-    for (i = 1; i < argc && i<sizeof(arglist)/sizeof(arglist[0]); i++) {
-		if(JSVAL_IS_DOUBLE(argv[i]))
-			arglist[i-1]=(char*)(unsigned long)*JSVAL_TO_DOUBLE(argv[i]);
-		else if(JSVAL_IS_INT(argv[i]))
-			arglist[i-1]=(char *)JSVAL_TO_INT(argv[i]);
-		else {
-			if((str=JS_ValueToString(cx, argv[i]))==NULL) {
-				JS_ReportError(cx,"JS_ValueToString failed");
-			    return(JS_FALSE);
-			}
-			arglist[i-1]=JS_GetStringBytes(str);
-		}
-	}
-
-	if((cp=JS_vsmprintf(JS_GetStringBytes(fmt),(char*)arglist))==NULL) {
-		JS_ReportError(cx,"JS_vsmprintf failed");
+	if((cp=js_sprintf(cx, 0, argc, argv))==NULL) {
+		JS_ReportError(cx,"js_sprintf failed");
 		return(JS_FALSE);
 	}
 
 	*rval = INT_TO_JSVAL(fwrite(cp,1,strlen(cp),p->fp));
-	JS_smprintf_free(cp);
+	free(cp);
 	
     return(JS_TRUE);
 }
diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index 5f352d3593..3eca314bb2 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -42,9 +42,6 @@
 #include "base64.h"
 #include "htmlansi.h"
 #include "ini_file.h"
-#ifdef USE_XP_PRINTF
-	#include "xpprintf.h"
-#endif
 
 #define MAX_ANSI_SEQ	16
 #define MAX_ANSI_PARAMS	8
@@ -284,82 +281,19 @@ js_load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
     return(success);
 }
 
-#ifdef USE_XP_PRINTF
-
-static JSBool
-js_format(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-	char*		fmt;
-    uintN		i;
-    JSString*	str;
-
-	if((fmt=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
-		return(JS_FALSE);
-
-	fmt=xp_asprintf_start(fmt);
-    for(i=1; i<argc; i++) {
-		if(JSVAL_IS_DOUBLE(argv[i]))
-			fmt=xp_asprintf_next(fmt,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_DOUBLE,*JSVAL_TO_DOUBLE(argv[i]));
-		else if(JSVAL_IS_INT(argv[i]))
-			fmt=xp_asprintf_next(fmt,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_INT,JSVAL_TO_INT(argv[i]));
-		else if(JSVAL_IS_BOOLEAN(argv[i]) && xp_printf_get_type(fmt)!=XP_PRINTF_TYPE_CHARP)
-			fmt=xp_asprintf_next(fmt,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_INT,JSVAL_TO_BOOLEAN(argv[i]));
-		else {
-			if((str=JS_ValueToString(cx, argv[i]))==NULL) {
-				JS_ReportError(cx,"JS_ValueToString failed");
-			    return(JS_FALSE);
-			}
-			fmt=xp_asprintf_next(fmt,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_CHARP,JS_GetStringBytes(str));
-		}
-	}
-
-	fmt=xp_asprintf_end(fmt);
-	
-	str = JS_NewStringCopyZ(cx, fmt);
-	free(fmt);
-
-	if(str==NULL)
-		return(JS_FALSE);
-
-	*rval = STRING_TO_JSVAL(str);
-    return(JS_TRUE);
-}
-
-#else
-
 static JSBool
 js_format(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 	char*		p;
-	char*		fmt;
-    uintN		i;
-    JSString *	str;
-	va_list		arglist[64];
+    JSString*	str;
 
-	if((fmt=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
+	if((p=js_sprintf(cx, 0, argc, argv))==NULL) {
+		JS_ReportError(cx,"js_sprintf failed");
 		return(JS_FALSE);
-
-	memset(arglist,0,sizeof(arglist));	/* Initialize arglist to NULLs */
-
-    for (i = 1; i < argc && i<sizeof(arglist)/sizeof(arglist[0]); i++) {
-		if(JSVAL_IS_DOUBLE(argv[i]))
-			arglist[i-1]=(char*)(unsigned long)*JSVAL_TO_DOUBLE(argv[i]);
-		else if(JSVAL_IS_INT(argv[i]))
-			arglist[i-1]=(char *)JSVAL_TO_INT(argv[i]);
-		else {
-			if((str=JS_ValueToString(cx, argv[i]))==NULL) {
-				JS_ReportError(cx,"JS_ValueToString failed");
-			    return(JS_FALSE);
-			}
-			arglist[i-1]=JS_GetStringBytes(str);
-		}
 	}
-	
-	if((p=JS_vsmprintf(fmt,(char*)arglist))==NULL)
-		return(JS_FALSE);
 
 	str = JS_NewStringCopyZ(cx, p);
-	JS_smprintf_free(p);
+	free(p);
 
 	if(str==NULL)
 		return(JS_FALSE);
@@ -368,9 +302,6 @@ js_format(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
     return(JS_TRUE);
 }
 
-#endif
-
-
 static JSBool
 js_yield(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
diff --git a/src/sbbs3/js_sprintf.c b/src/sbbs3/js_sprintf.c
new file mode 100644
index 0000000000..784284d19d
--- /dev/null
+++ b/src/sbbs3/js_sprintf.c
@@ -0,0 +1,67 @@
+/* js_sprintf.c */
+
+/* Synchronet JavaScript "[s]printf" implementation */
+
+/* $Id$ */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html		*
+ *																			*
+ * This program is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU General Public License				*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU General Public License for more details: gpl.txt or			*
+ * http://www.fsf.org/copyleft/gpl.html										*
+ *																			*
+ * Anonymous FTP access to the most recent released source is available at	*
+ * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
+ *																			*
+ * Anonymous CVS access to the development source and modification history	*
+ * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
+ *     (just hit return, no password is necessary)							*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * You are encouraged to submit any modifications (preferably in Unix diff	*
+ * format) via e-mail to mods@synchro.net									*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
+
+#include "sbbs.h"
+#include "xpprintf.h"	/* Hurrah for Deuce! */
+
+char* DLLCALL
+js_sprintf(JSContext *cx, uint argn, uintN argc, jsval *argv)
+{
+	char*		p;
+    JSString*	str;
+
+	if((p=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
+		return(NULL);
+
+	p=xp_asprintf_start(p);
+    for(; argn<argc; argn++) {
+		if(JSVAL_IS_DOUBLE(argv[argn]))
+			p=xp_asprintf_next(p,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_DOUBLE,*JSVAL_TO_DOUBLE(argv[argn]));
+		else if(JSVAL_IS_INT(argv[argn]))
+			p=xp_asprintf_next(p,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_INT,JSVAL_TO_INT(argv[argn]));
+		else if(JSVAL_IS_BOOLEAN(argv[argn]) && xp_printf_get_type(p)!=XP_PRINTF_TYPE_CHARP)
+			p=xp_asprintf_next(p,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_INT,JSVAL_TO_BOOLEAN(argv[argn]));
+		else {
+			if((str=JS_ValueToString(cx, argv[argn]))==NULL)
+			    return(NULL);
+			p=xp_asprintf_next(p,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_CHARP,JS_GetStringBytes(str));
+		}
+	}
+
+	return xp_asprintf_end(p);
+
+}
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index 48c36c44e9..23fe1c0f7d 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -345,39 +345,18 @@ js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 static JSBool
 js_printf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
-	char*		p;
-    uintN		i;
-	JSString *	fmt;
-    JSString *	str;
-	va_list		arglist[64];
+	char* p;
 
-	if((fmt = JS_ValueToString(cx, argv[0]))==NULL)
+	if((p = js_sprintf(cx, 0, argc, argv))==NULL) {
+		JS_ReportError(cx,"js_sprintf failed");
 		return(JS_FALSE);
-
-	memset(arglist,0,sizeof(arglist));	/* Initialize arglist to NULLs */
-
-    for (i = 1; i < argc && i<sizeof(arglist)/sizeof(arglist[0]); i++) {
-		if(JSVAL_IS_DOUBLE(argv[i]))
-			arglist[i-1]=(char*)(unsigned long)-1;//*JSVAL_TO_DOUBLE(argv[i]);
-		else if(JSVAL_IS_INT(argv[i]))
-			arglist[i-1]=(char *)JSVAL_TO_INT(argv[i]);
-		else {
-			if((str=JS_ValueToString(cx, argv[i]))==NULL) {
-				JS_ReportError(cx,"JS_ValueToString failed");
-			    return(JS_FALSE);
-			}
-			arglist[i-1]=JS_GetStringBytes(str);
-		}
 	}
-	
-	if((p=JS_vsmprintf(JS_GetStringBytes(fmt),(char*)arglist))==NULL)
-		return(JS_FALSE);
 
 	fprintf(confp,"%s",p);
 
 	*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, p));
 
-	JS_smprintf_free(p);
+	free(p);
 
     return(JS_TRUE);
 }
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 30a5badba5..48f60264b0 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -693,36 +693,15 @@ static JSBool
 js_printf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 	char*		p;
-    uintN		i;
-	JSString *	fmt;
-    JSString *	str;
 	sbbs_t*		sbbs;
-	va_list		arglist[64];
 
 	if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
 		return(JS_FALSE);
 
-	if((fmt = JS_ValueToString(cx, argv[0]))==NULL)
+	if((p = js_sprintf(cx, 0, argc, argv))==NULL) {
+		JS_ReportError(cx,"js_sprintf failed");
 		return(JS_FALSE);
-
-	memset(arglist,0,sizeof(arglist));	// Initialize arglist to NULLs
-
-    for (i = 1; i < argc && i<sizeof(arglist)/sizeof(arglist[0]); i++) {
-		if(JSVAL_IS_DOUBLE(argv[i]))
-			arglist[i-1]=(char*)(unsigned long)*JSVAL_TO_DOUBLE(argv[i]);
-		else if(JSVAL_IS_INT(argv[i]))
-			arglist[i-1]=(char *)JSVAL_TO_INT(argv[i]);
-		else {
-			if((str=JS_ValueToString(cx, argv[i]))==NULL) {
-				JS_ReportError(cx,"JS_ValueToString failed");
-			    return(JS_FALSE);
-			}
-			arglist[i-1]=JS_GetStringBytes(str);
-		}
 	}
-	
-	if((p=JS_vsmprintf(JS_GetStringBytes(fmt),(char*)arglist))==NULL)
-		return(JS_FALSE);
 
 	if(sbbs->online==ON_LOCAL)
 		eprintf(LOG_INFO,"%s",p);
@@ -731,7 +710,7 @@ js_printf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
 	*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, p));
 
-	JS_smprintf_free(p);
+	free(p);
 
     return(JS_TRUE);
 }
diff --git a/src/sbbs3/objects.mk b/src/sbbs3/objects.mk
index 5e172beac0..e465b34176 100644
--- a/src/sbbs3/objects.mk
+++ b/src/sbbs3/objects.mk
@@ -52,6 +52,7 @@ OBJS	=	$(MTOBJODIR)$(DIRSEP)ansiterm$(OFILE) \
 			$(MTOBJODIR)$(DIRSEP)js_queue$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_server$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_socket$(OFILE)\
+			$(MTOBJODIR)$(DIRSEP)js_sprintf$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_system$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_user$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_xtrn_area$(OFILE)\
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index afe6567a40..e40c2c5ac6 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -8,7 +8,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html		*
  *																			*
  * This program is free software; you can redistribute it and/or			*
  * modify it under the terms of the GNU General Public License				*
@@ -1023,6 +1023,9 @@ extern "C" {
 	/* js_file.c */
 	DLLEXPORT JSObject* DLLCALL js_CreateFileClass(JSContext* cx, JSObject* parent);
 
+	/* js_sprintf.c */
+	DLLEXPORT char*		DLLCALL js_sprintf(JSContext* cx, uint argn, uintN argc, jsval *argv);
+
 	/* js_console.cpp */
 	JSObject* js_CreateConsoleObject(JSContext* cx, JSObject* parent);
 
-- 
GitLab