浏览代码

Version of printf that doesn't suffer from buffer overflows (#1564)

Philip Gladstone 7 年之前
父节点
当前提交
ebb537c502

+ 4 - 3
app/http/httpclient.c

@@ -13,6 +13,7 @@
  */
 
 #include "osapi.h"
+#include "../libc/c_stdio.h"
 #include "user_interface.h"
 #include "espconn.h"
 #include "mem.h"
@@ -645,10 +646,10 @@ void ICACHE_FLASH_ATTR http_put( const char * url, const char * headers, const c
 
 void ICACHE_FLASH_ATTR http_callback_example( char * response, int http_status, char * full_response )
 {
-	os_printf( "http_status=%d\n", http_status );
+	dbg_printf( "http_status=%d\n", http_status );
 	if ( http_status != HTTP_STATUS_GENERIC_ERROR )
 	{
-		os_printf( "strlen(full_response)=%d\n", strlen( full_response ) );
-		os_printf( "response=%s<EOF>\n", response );
+		dbg_printf( "strlen(full_response)=%d\n", strlen( full_response ) );
+		dbg_printf( "response=%s<EOF>\n", response );
 	}
 }

+ 1 - 1
app/http/httpclient.h

@@ -14,7 +14,7 @@
 #define HTTPCLIENT_DEBUG_ON
 #endif
 #if defined(HTTPCLIENT_DEBUG_ON)
-#define HTTPCLIENT_DEBUG(format, ...) os_printf(format, ##__VA_ARGS__)
+#define HTTPCLIENT_DEBUG(format, ...) dbg_printf(format, ##__VA_ARGS__)
 #else
 #define HTTPCLIENT_DEBUG(format, ...)
 #endif

+ 2 - 2
app/include/user_config.h

@@ -36,13 +36,13 @@ extern void luaL_assertfail(const char *file, int line, const char *message);
 #define NODE_ERROR
 
 #ifdef NODE_DEBUG
-#define NODE_DBG c_printf
+#define NODE_DBG dbg_printf
 #else
 #define NODE_DBG
 #endif	/* NODE_DEBUG */
 
 #ifdef NODE_ERROR
-#define NODE_ERR c_printf
+#define NODE_ERR dbg_printf
 #else
 #define NODE_ERR
 #endif	/* NODE_ERROR */

+ 2 - 0
app/libc/c_stdio.h

@@ -63,6 +63,8 @@ extern void output_redirect(const char *str);
 int c_sprintf(char* s,const char *fmt, ...);
 #endif
 
+extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+
 #define c_vsprintf ets_vsprintf
 #define c_printf(...) do {					\
 	unsigned char __print_buf[BUFSIZ];		\

+ 164 - 0
app/libc/dbg_printf.c

@@ -0,0 +1,164 @@
+/*	$NetBSD: printf.c,v 1.12 1997/06/26 19:11:48 drochner Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)printf.c	8.1 (Berkeley) 6/11/93
+ */
+
+// This version uses almost no stack, and does not suffer from buffer 
+// overflows. The downside is that it does not implement a wide range
+// of formatting characters.
+
+#include <c_stdlib.h>
+#include <c_types.h>
+#include <c_stdarg.h>
+#include "driver/uart.h"
+
+static void kprintn (void (*)(const char), uint32_t, int, int, char);
+static void kdoprnt (void (*)(const char), const char *, va_list);
+
+void
+dbg_printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	kdoprnt(uart0_putc, fmt, ap);
+	va_end(ap);
+}
+
+void
+dbg_vprintf(const char *fmt, va_list ap)
+{
+	kdoprnt(uart0_putc, fmt, ap);
+}
+
+void
+kdoprnt(void (*put)(const char), const char *fmt, va_list ap)
+{
+	register char *p;
+	register int ch, n;
+	unsigned long ul;
+	int lflag, set;
+        char zwidth;
+        char width;
+
+	for (;;) {
+		while ((ch = *fmt++) != '%') {
+			if (ch == '\0')
+				return;
+			put(ch);
+		}
+		lflag = 0;
+                width = 0;
+                zwidth = ' ';
+reswitch:	switch (ch = *fmt++) {
+		case '\0':
+			/* XXX print the last format character? */
+			return;
+		case 'l':
+			lflag = 1;
+			goto reswitch;
+		case 'c':
+			ch = va_arg(ap, int);
+				put(ch & 0x7f);
+			break;
+		case 's':
+			p = va_arg(ap, char *);
+                        if (p == 0) {
+                          p = "<null>";
+                        }
+			while ((ch = *p++))
+				put(ch);
+			break;
+		case 'd':
+			ul = lflag ?
+			    va_arg(ap, long) : va_arg(ap, int);
+			if ((long)ul < 0) {
+				put('-');
+				ul = -(long)ul;
+			}
+			kprintn(put, ul, 10, width, zwidth);
+			break;
+		case 'o':
+			ul = lflag ?
+			    va_arg(ap, uint32_t) : va_arg(ap, uint32_t);
+			kprintn(put, ul, 8, width, zwidth);
+			break;
+		case 'u':
+			ul = lflag ?
+			    va_arg(ap, uint32_t) : va_arg(ap, uint32_t);
+			kprintn(put, ul, 10, width, zwidth);
+			break;
+		case 'x':
+			ul = lflag ?
+			    va_arg(ap, uint32_t) : va_arg(ap, uint32_t);
+			kprintn(put, ul, 16, width, zwidth);
+			break;
+		default:
+                        if (ch >= '0' && ch <= '9') {
+                          if (ch == '0' && width == 0 && zwidth == ' ') {
+                            zwidth = '0';
+                          } else {
+                            width = width * 10 + ch - '0';
+                          }
+                          goto reswitch;
+                        }
+			put('%');
+			if (lflag)
+				put('l');
+			put(ch);
+		}
+	}
+	va_end(ap);
+}
+
+static void
+kprintn(void (*put)(const char), unsigned long ul, int base, int width, char padchar)
+{
+					/* hold a long in base 8 */
+	char *p, buf[(sizeof(long) * 8 / 3) + 2];
+
+	p = buf;
+	do {
+		*p++ = "0123456789abcdef"[ul % base];
+	} while (ul /= base);
+        
+        while (p - buf < width--) {
+          put(padchar);
+        }
+
+	do {
+		put(*--p);
+	} while (p > buf);
+}

+ 1 - 1
app/lua/lauxlib.c

@@ -807,7 +807,7 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
 }
 
 LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) {
-  c_printf("ASSERT@%s(%d): %s\n", file, line, message); 
+  dbg_printf("ASSERT@%s(%d): %s\n", file, line, message); 
 }
 
 static int panic (lua_State *L) {

+ 1 - 1
app/lua/luaconf.h

@@ -346,7 +346,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
 ** (A format string with one argument is enough for Lua...)
 */
 #if !defined(LUA_USE_STDIO)
-#define luai_writestringerror(s,p)	c_printf((s), (p))
+#define luai_writestringerror(s,p)	dbg_printf((s), (p))
 #endif // defined(LUA_USE_STDIO)
 
 

+ 3 - 3
app/modules/http.c

@@ -14,13 +14,13 @@ static int http_callback_registry  = LUA_NOREF;
 static void http_callback( char * response, int http_status, char * full_response )
 {
 #if defined(HTTPCLIENT_DEBUG_ON)
-  c_printf( "http_status=%d\n", http_status );
+  dbg_printf( "http_status=%d\n", http_status );
   if ( http_status != HTTP_STATUS_GENERIC_ERROR )
   {
     if (full_response != NULL) {
-      c_printf( "strlen(full_response)=%d\n", strlen( full_response ) );
+      dbg_printf( "strlen(full_response)=%d\n", strlen( full_response ) );
     }
-    c_printf( "response=%s<EOF>\n", response );
+    dbg_printf( "response=%s<EOF>\n", response );
   }
 #endif
   if (http_callback_registry != LUA_NOREF)

+ 1 - 1
app/modules/sntp.c

@@ -53,7 +53,7 @@
 #define MAX_ATTEMPTS 5
 
 #if 0
-# define sntp_dbg(...) c_printf(__VA_ARGS__)
+# define sntp_dbg(...) dbg_printf(__VA_ARGS__)
 #else
 # define sntp_dbg(...)
 #endif

+ 1 - 1
app/net/nodemcu_mdns.c

@@ -52,7 +52,7 @@
 #include "nodemcu_mdns.h"
 
 #if 0
-#define MDNS_DBG(...)  os_printf(...)
+#define MDNS_DBG(...)  dbg_printf(...)
 #else
 #define MDNS_DBG(...)  do {} while (0)
 #endif

+ 5 - 5
app/spiffs/spiffs_config.h

@@ -20,19 +20,19 @@
 
 // Set generic spiffs debug output call.
 #ifndef SPIFFS_DBG
-#define SPIFFS_DBG(...) //printf(__VA_ARGS__)
+#define SPIFFS_DBG(...) //dbg_printf(__VA_ARGS__)
 #endif
 // Set spiffs debug output call for garbage collecting.
 #ifndef SPIFFS_GC_DBG
-#define SPIFFS_GC_DBG(...) //printf(__VA_ARGS__)
+#define SPIFFS_GC_DBG(...) //dbg_printf(__VA_ARGS__)
 #endif
 // Set spiffs debug output call for caching.
 #ifndef SPIFFS_CACHE_DBG
-#define SPIFFS_CACHE_DBG(...) //printf(__VA_ARGS__)
+#define SPIFFS_CACHE_DBG(...) //dbg_printf(__VA_ARGS__)
 #endif
 // Set spiffs debug output call for system consistency checks.
 #ifndef SPIFFS_CHECK_DBG
-#define SPIFFS_CHECK_DBG(...) //printf(__VA_ARGS__)
+#define SPIFFS_CHECK_DBG(...) //dbg_printf(__VA_ARGS__)
 #endif
 
 // Enable/disable API functions to determine exact number of bytes
@@ -211,7 +211,7 @@
 #endif
 #if SPIFFS_TEST_VISUALISATION
 #ifndef spiffs_printf
-#define spiffs_printf(...)                printf(__VA_ARGS__)
+#define spiffs_printf(...)                dbg_printf(__VA_ARGS__)
 #endif
 // spiffs_printf argument for a free page
 #ifndef SPIFFS_TEST_VIS_FREE_STR

+ 1 - 1
app/user/user_main.c

@@ -141,7 +141,7 @@ void nodemcu_init(void)
 #ifdef BUILD_SPIFFS
     if (!vfs_mount("/FLASH", 0)) {
         // Failed to mount -- try reformat
-	c_printf("Formatting file system. Please wait...\n");
+	dbg_printf("Formatting file system. Please wait...\n");
         if (!vfs_format()) {
             NODE_ERR( "\n*** ERROR ***: unable to format. FS might be compromised.\n" );
             NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" );

+ 1 - 1
tools/spiffsimg/Makefile

@@ -2,7 +2,7 @@ SRCS=\
 	main.c \
   ../../app/spiffs/spiffs_cache.c  ../../app/spiffs/spiffs_check.c  ../../app/spiffs/spiffs_gc.c  ../../app/spiffs/spiffs_hydrogen.c  ../../app/spiffs/spiffs_nucleus.c
 
-CFLAGS=-g -Wall -Wextra -Wno-unused-parameter -Wno-unused-function -I. -I../../app/spiffs -I../../app/include -DNODEMCU_SPIFFS_NO_INCLUDE --include spiffs_typedefs.h
+CFLAGS=-g -Wall -Wextra -Wno-unused-parameter -Wno-unused-function -I. -I../../app/spiffs -I../../app/include -DNODEMCU_SPIFFS_NO_INCLUDE --include spiffs_typedefs.h -Ddbg_printf=printf
 
 spiffsimg: $(SRCS)
 	$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@