~ chicken-core (chicken-5) 8efbbc50d050d28c34ea0c5a58d0de92ec9f918a


commit 8efbbc50d050d28c34ea0c5a58d0de92ec9f918a
Author:     Christian Kellermann <ckeen@pestilenz.org>
AuthorDate: Fri Jan 10 15:43:07 2014 +0100
Commit:     Christian Kellermann <ckeen@pestilenz.org>
CommitDate: Tue Feb 4 12:14:22 2014 +0100

    Replace unsafe string functions with their safer counterparts
    
    This patch removes strcpy, strcat and sprintf usage out of core in
    favor for strlcpy, strlcat and snprintf. For systems that don't
    include strlcat and strlcpy in their string.h, drop-in replacements
    for these two functions are provided, derived from public code by
    C.B. Falconer.
    
    Systems that *do* ship these functions should declare HAVE_STRLCPY and
    HAVE_STRLCAT in their chicken-config.h.
    
    The chicken definitions for strcpy and strcat have been removed.
    
    This has been done for the Makefile.bsd as these do ship with these
    procedures.
    
    Some Windows/Unix POSIX duplication has been pulled into the posix-common
    file used on both platforms.
    
    Signed-off-by: Peter Bex <peter.bex@xs4all.nl>

diff --git a/Makefile.bsd b/Makefile.bsd
index 0dbc247a..4dd003fa 100644
--- a/Makefile.bsd
+++ b/Makefile.bsd
@@ -86,6 +86,8 @@ chicken-config.h: chicken-defaults.h
 	echo "#define HAVE_STRERROR 1" >>$@
 	echo "#define HAVE_STRINGS_H 1" >>$@
 	echo "#define HAVE_STRING_H 1" >>$@
+	echo "#define HAVE_STRLCAT 1" >>$@
+	echo "#define HAVE_STRLCPY 1" >>$@
 	echo "#define HAVE_STRTOLL 1" >>$@
 	echo "#define HAVE_STRTOQ 1" >>$@
 	echo "#define HAVE_SYS_STAT_H 1" >>$@
diff --git a/chicken.h b/chicken.h
index bd6c23d7..6b8fc6a1 100644
--- a/chicken.h
+++ b/chicken.h
@@ -1,3 +1,4 @@
+
 /* chicken.h - General headerfile for compiler generated executables
 ;
 ; Copyright (c) 2008-2014, The Chicken Team
@@ -922,12 +923,12 @@ DECL_C_PROC_p0 (128,  1,0,0,0,0,0,0,0)
 
 # define C_memcpy                   memcpy
 # define C_memcmp                   memcmp
-# define C_strcpy                   strcpy
+# define C_strlcpy                  strlcpy
 # define C_strncpy                  strncpy
 # define C_strcmp                   strcmp
 # define C_strncmp                  strncmp
 # define C_strlen                   strlen
-# define C_strcat                   strcat
+# define C_strlcat                  strlcat
 # define C_memset                   memset
 # define C_memmove                  memmove
 # define C_strncasecmp              strncasecmp
@@ -944,7 +945,6 @@ DECL_C_PROC_p0 (128,  1,0,0,0,0,0,0,0)
 # define C_fopen                    fopen
 # define C_fclose                   fclose
 # define C_strpbrk                  strpbrk
-# define C_sprintf                  sprintf
 # define C_snprintf                 snprintf
 # define C_printf                   printf
 # define C_fprintf                  fprintf
@@ -1308,7 +1308,7 @@ extern double trunc(double);
 #define C_rename_file(old, new)         C_fix(rename(C_c_string(old), C_c_string(new)))
 #define C_delete_file(fname)            C_fix(remove(C_c_string(fname)))
 #define C_poke_double(b, i, n)          (((double *)C_data_pointer(b))[ C_unfix(i) ] = C_c_double(n), C_SCHEME_UNDEFINED)
-#define C_poke_c_string(b, i, from)     (C_strcpy((char *)C_block_item(b, C_unfix(i)), C_data_pointer(from)), C_SCHEME_UNDEFINED)
+#define C_poke_c_string(b, i, from, s)  (C_strlcpy((char *)C_block_item(b, C_unfix(i)), C_data_pointer(from), s), C_SCHEME_UNDEFINED)
 #define C_peek_fixnum(b, i)             C_fix(C_block_item(b, C_unfix(i)))
 #define C_peek_byte(ptr, i)             C_fix(((unsigned char *)C_u_i_car(ptr))[ C_unfix(i) ])
 #define C_dupstr(s)                     C_strdup(C_data_pointer(s))
@@ -2913,9 +2913,9 @@ C_path_to_executable(C_char *fname)
 	
   pid = C_getpid();
 #  ifdef __linux__
-  C_sprintf(linkname, "/proc/%i/exe", pid);
+  C_snprintf(linkname, sizeof(linkname), "/proc/%i/exe", pid);
 #  else
-  C_sprintf(linkname, "/proc/%i/path/a.out", pid); /* SunOS / Solaris */
+  C_snprintf(linkname, sizeof(linkname), "/proc/%i/path/a.out", pid); /* SunOS / Solaris */
 #  endif
   ret = C_readlink(linkname, buffer, C_MAX_PATH - 1);
 
@@ -2965,7 +2965,7 @@ C_path_to_executable(C_char *fname)
   /* absolute path */
   if(*fname == '/') {
     fname[ i ] = '\0';
-    C_strcpy(buffer, fname);
+    C_strlcpy(buffer, fname, C_MAX_PATH);
     return buffer;
   }
   else {
@@ -2973,8 +2973,8 @@ C_path_to_executable(C_char *fname)
     if(C_getcwd(buffer, C_MAX_PATH - 1) == NULL)
       return NULL;
 
-    C_strcat(buffer, "/");
-    C_strcat(buffer, fname);
+    C_strlcat(buffer, "/", C_MAX_PATH);
+    C_strlcat(buffer, fname, C_MAX_PATH);
   
     if(C_access(buffer, F_OK) == 0) {
       for(i = C_strlen(buffer); i >= 0 && buffer[ i ] != '/'; --i);
@@ -2999,8 +2999,8 @@ C_path_to_executable(C_char *fname)
       case ':':
 	C_strncpy(buffer, path + j, k - j);
 	buffer[ k - j ] = '\0';
-	C_strcat(buffer, "/");
-	C_strcat(buffer, fname);
+	C_strlcat(buffer, "/", C_MAX_PATH);
+	C_strlcat(buffer, fname, C_MAX_PATH);
 
 	if(C_access(buffer, F_OK) == 0) {
 	  dname = C_strdup(buffer);
@@ -3037,7 +3037,7 @@ C_path_to_executable(C_char *fname)
 
   while (get_next_image_info(0, &cookie, &info) == B_OK) {
     if (info.type == B_APP_IMAGE) {
-      C_strcpy(buffer, info.name);
+      C_strlcpy(buffer, info.name, C_MAX_PATH);
 
       for(i = C_strlen(buffer); i >= 0 && buffer[ i ] != '/'; --i);
 
@@ -3054,6 +3054,36 @@ C_path_to_executable(C_char *fname)
 }
 #endif
 
+/* These strl* functions are based on public domain code by C.B. Falconer */
+#ifndef HAVE_STRLCPY
+C_inline size_t strlcpy(char *dst, const char *src, size_t sz)
+{
+   const char *start = src;
+
+   if (sz--) {
+      while ((*dst++ = *src))
+         if (sz--) src++;
+         else {
+            *(--dst) = '\0';
+            break;
+         }
+   }
+   while (*src++) continue;
+   return src - start - 1;
+}
+#endif
+
+#ifndef HAVE_STRLCAT
+C_inline size_t strlcat(char *dst, const char *src, size_t sz)
+{
+   char  *start = dst;
+
+   while (*dst++)    /* assumes sz >= strlen(dst) */
+      if (sz) sz--;    /* i.e. well formed string */
+   dst--;
+   return dst - start + strlcpy(dst, src, sz);
+}
+#endif
 
 C_END_C_DECLS
 
diff --git a/library.scm b/library.scm
index bf8a1941..6194e537 100644
--- a/library.scm
+++ b/library.scm
@@ -4375,7 +4375,7 @@ EOF
     str2 ) )
 
 (define (##sys#poke-c-string b i s) 
-  (##core#inline "C_poke_c_string" b i (##sys#make-c-string s)) )
+  (##core#inline "C_poke_c_string" b i (##sys#make-c-string s) s) )
 
 (define (##sys#poke-integer b i n) (##core#inline "C_poke_integer" b i n))
 (define (##sys#poke-double b i n) (##core#inline "C_poke_double" b i n))
diff --git a/posix-common.scm b/posix-common.scm
index d14b4c68..3911b07b 100644
--- a/posix-common.scm
+++ b/posix-common.scm
@@ -91,6 +91,36 @@ static char C_time_string [TIME_STRING_MAXLENGTH + 1];
 
 #define C_set_file_ptr(port, ptr)  (C_set_block_item(port, 0, (C_block_item(ptr, 0))), C_SCHEME_UNDEFINED)
 
+#define C_opendir(x,h)      C_set_block_item(h, 0, (C_word) opendir(C_c_string(x)))
+#define C_closedir(h)       (closedir((DIR *)C_block_item(h, 0)), C_SCHEME_UNDEFINED)
+#define C_readdir(h,e)      C_set_block_item(e, 0, (C_word) readdir((DIR *)C_block_item(h, 0)))
+#define C_foundfile(e,b,l)    (C_strlcpy(C_c_string(b), ((struct dirent *) C_block_item(e, 0))->d_name, l), C_fix(strlen(((struct dirent *) C_block_item(e, 0))->d_name)))
+
+#ifdef C_GNU_ENV
+# define C_unsetenv(s)      (unsetenv((char *)C_data_pointer(s)), C_SCHEME_TRUE)
+# define C_setenv(x, y)     C_fix(setenv((char *)C_data_pointer(x), (char *)C_data_pointer(y), 1))
+#else
+# if defined(_WIN32) && !defined(__CYGWIN__)
+#  define C_unsetenv(s)      C_fix(C_setenv(s, C_SCHEME_FALSE))
+# else
+#  define C_unsetenv(s)      C_fix(putenv((char *)C_data_pointer(s)))
+# endif
+static C_word C_fcall C_setenv(C_word x, C_word y) {
+  char *sx = C_c_string(x),
+       *sy = (y == C_SCHEME_FALSE ? "" : C_c_string(y));
+  int n1 = C_strlen(sx), n2 = C_strlen(sy);
+  int buf_len = n1 + n2 + 2;
+  char *buf = (char *)C_malloc(buf_len);
+  if(buf == NULL) return(C_fix(0));
+  else {
+    C_strlcpy(buf, sx, buf_len);
+    buf[ n1 ] = '=';
+    C_strlcat(buf + n1 + 1, sy, buf_len);
+    return(C_fix(putenv(buf)));
+  }
+}
+#endif
+
 EOF
 ))
 
@@ -385,7 +415,7 @@ EOF
 		(begin
 		  (##core#inline "C_closedir" handle)
 		  '() )
-		(let* ([flen (##core#inline "C_foundfile" entry buffer)]
+		(let* ([flen (##core#inline "C_foundfile" entry buffer (string-length buffer))]
 		       [file (##sys#substring buffer 0 flen)]
 		       [char1 (string-ref file 0)]
 		       [char2 (and (fx> flen 1) (string-ref file 1))] )
@@ -525,6 +555,35 @@ EOF
                 (##sys#error 'time->string "cannot convert time vector to string" tm) ) ) ) ) ) )
 
 
+;;; Environment access:
+
+(define setenv
+  (lambda (var val)
+    (##sys#check-string var 'setenv)
+    (##sys#check-string val 'setenv)
+    (##core#inline "C_setenv" (##sys#make-c-string var 'setenv) (##sys#make-c-string val 'setenv))
+    (##core#undefined) ) )
+
+(define (unsetenv var)
+  (##sys#check-string var 'unsetenv)
+  (##core#inline "C_unsetenv" (##sys#make-c-string var 'unsetenv))
+  (##core#undefined) )
+
+(define get-environment-variables
+  (let ([get (foreign-lambda c-string "C_getenventry" int)])
+    (lambda ()
+      (let loop ([i 0])
+        (let ([entry (get i)])
+          (if entry
+              (let scan ([j 0])
+                (if (char=? #\= (##core#inline "C_subchar" entry j))
+                    (cons (cons (##sys#substring entry 0 j)
+                                (##sys#substring entry (fx+ j 1) (##sys#size entry)))
+                          (loop (fx+ i 1)))
+                    (scan (fx+ j 1)) ) )
+              '() ) ) ) ) ) )
+
+
 ;;; Signals
 
 (define (set-signal-handler! sig proc)
diff --git a/posixunix.scm b/posixunix.scm
index da0d9f91..224e9b02 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -152,11 +152,6 @@ static C_TLS struct stat C_statbuf;
 #define C_chdir(str)        C_fix(chdir(C_c_string(str)))
 #define C_rmdir(str)        C_fix(rmdir(C_c_string(str)))
 
-#define C_opendir(x,h)      C_set_block_item(h, 0, (C_word) opendir(C_c_string(x)))
-#define C_closedir(h)       (closedir((DIR *)C_block_item(h, 0)), C_SCHEME_UNDEFINED)
-#define C_readdir(h,e)      C_set_block_item(e, 0, (C_word) readdir((DIR *)C_block_item(h, 0)))
-#define C_foundfile(e,b)    (strcpy(C_c_string(b), ((struct dirent *) C_block_item(e, 0))->d_name), C_fix(strlen(((struct dirent *) C_block_item(e, 0))->d_name)))
-
 #define open_binary_input_pipe(a, n, name)   C_mpointer(a, popen(C_c_string(name), "r"))
 #define open_text_input_pipe(a, n, name)     open_binary_input_pipe(a, n, name)
 #define open_binary_output_pipe(a, n, name)  C_mpointer(a, popen(C_c_string(name), "w"))
@@ -204,26 +199,6 @@ static C_TLS struct stat C_statbuf;
 
 #define C_lstat(fn)         C_fix(lstat((char *)C_data_pointer(fn), &C_statbuf))
 
-#ifdef C_GNU_ENV
-# define C_unsetenv(s)      (unsetenv((char *)C_data_pointer(s)), C_SCHEME_TRUE)
-# define C_setenv(x, y)     C_fix(setenv((char *)C_data_pointer(x), (char *)C_data_pointer(y), 1))
-#else
-# define C_unsetenv(s)      C_fix(putenv((char *)C_data_pointer(s)))
-static C_word C_fcall C_setenv(C_word x, C_word y) {
-  char *sx = C_data_pointer(x),
-       *sy = C_data_pointer(y);
-  int n1 = C_strlen(sx), n2 = C_strlen(sy);
-  char *buf = (char *)C_malloc(n1 + n2 + 2);
-  if(buf == NULL) return(C_fix(0));
-  else {
-    C_strcpy(buf, sx);
-    buf[ n1 ] = '=';
-    C_strcpy(buf + n1 + 1, sy);
-    return(C_fix(putenv(buf)));
-  }
-}
-#endif
-
 static void C_fcall C_set_arg_string(char **where, int i, char *a, int len) {
   char *ptr;
   if(a != NULL) {
@@ -1505,35 +1480,6 @@ EOF
 	"system error while trying to access file" filename) ) ) ) )
 
 
-;;; Environment access:
-
-(define setenv
-  (lambda (var val)
-    (##sys#check-string var 'setenv)
-    (##sys#check-string val 'setenv)
-    (##core#inline "C_setenv" (##sys#make-c-string var 'setenv) (##sys#make-c-string val 'setenv))
-    (##core#undefined) ) )
-
-(define (unsetenv var)
-  (##sys#check-string var 'unsetenv)
-  (##core#inline "C_unsetenv" (##sys#make-c-string var 'unsetenv))
-  (##core#undefined) )
-
-(define get-environment-variables
-  (let ([get (foreign-lambda c-string "C_getenventry" int)])
-    (lambda ()
-      (let loop ([i 0])
-        (let ([entry (get i)])
-          (if entry
-              (let scan ([j 0])
-                (if (char=? #\= (##core#inline "C_subchar" entry j))
-                    (cons (cons (##sys#substring entry 0 j)
-                                (##sys#substring entry (fx+ j 1) (##sys#size entry)))
-                          (loop (fx+ i 1)))
-                    (scan (fx+ j 1)) ) )
-              '() ) ) ) ) ) )
-
-
 ;;; Memory mapped I/O:
 
 (define-foreign-variable _prot_read int "PROT_READ")
diff --git a/posixwin.scm b/posixwin.scm
index 3dbec6aa..b2c3e5cf 100644
--- a/posixwin.scm
+++ b/posixwin.scm
@@ -137,6 +137,7 @@ static DIR * C_fcall
 opendir(const char *name)
 {
     int name_len = strlen(name);
+    int what_len = name_len + 3;
     DIR *dir = (DIR *)malloc(sizeof(DIR));
     char *what;
     if (!dir)
@@ -144,18 +145,18 @@ opendir(const char *name)
 	errno = ENOMEM;
 	return NULL;
     }
-    what = (char *)malloc(name_len + 3);
+    what = (char *)malloc(what_len);
     if (!what)
     {
 	free(dir);
 	errno = ENOMEM;
 	return NULL;
     }
-    strcpy(what, name);
+    C_strlcpy(what, name, what_len);
     if (strchr("\\/", name[name_len - 1]))
-	strcat(what, "*");
+	C_strlcat(what, "*", what_len);
     else
-	strcat(what, "\\*");
+	C_strlcat(what, "\\*", what_len);
 
     dir->handle = _findfirst(what, &dir->fdata);
     if (dir->handle == -1)
@@ -203,11 +204,6 @@ readdir(DIR * dir)
 # define P_DETACH P_NOWAIT
 #endif
 
-#define C_opendir(x,h)		C_set_block_item(h, 0, (C_word) opendir(C_c_string(x)))
-#define C_closedir(h)		(closedir((DIR *)C_block_item(h, 0)), C_SCHEME_UNDEFINED)
-#define C_readdir(h,e)		C_set_block_item(e, 0, (C_word) readdir((DIR *)C_block_item(h, 0)))
-#define C_foundfile(e,b)	(strcpy(C_c_string(b), ((struct dirent *) C_block_item(e, 0))->d_name), C_fix(strlen(((struct dirent *) C_block_item(e, 0))->d_name)))
-
 #define open_binary_input_pipe(a, n, name)   C_mpointer(a, _popen(C_c_string(name), "r"))
 #define open_text_input_pipe(a, n, name)     open_binary_input_pipe(a, n, name)
 #define open_binary_output_pipe(a, n, name)  C_mpointer(a, _popen(C_c_string(name), "w"))
@@ -222,28 +218,8 @@ readdir(DIR * dir)
 
 #define C_getenventry(i)   environ[ i ]
 
-#define C_putenv(s)	    C_fix(putenv((char *)C_data_pointer(s)))
 #define C_lstat(fn)	    C_stat(fn)
 
-static C_word C_fcall
-C_setenv(C_word x, C_word y)
-{
-    char *sx = C_data_pointer(x),
-	 *sy = C_data_pointer(y);
-    int n1 = C_strlen(sx),
-	n2 = C_strlen(sy);
-    char *buf = (char *)C_malloc(n1 + n2 + 2);
-    if (buf == NULL)
-	return(C_fix(0));
-    else
-    {
-	C_strcpy(buf, sx);
-	buf[ n1 ] = '=';
-	C_strcpy(buf + n1 + 1, sy);
-	return(C_fix(putenv(buf)));
-    }
-}
-
 static void C_fcall
 C_set_arg_string(char **where, int i, char *dat, int len)
 {
@@ -509,7 +485,7 @@ get_shlcmd()
 	    char *cmdnam = C_isNT ? "\\cmd.exe" : "\\command.com";
 	    UINT len = GetSystemDirectory(C_shlcmd, sizeof(C_shlcmd) - strlen(cmdnam));
 	    if (len)
-		strcpy(C_shlcmd + len, cmdnam);
+		C_strlcpy(C_shlcmd + len, cmdnam, sizeof(C_shlcmd));
 	    else
 		return set_last_errno();
 	}
@@ -620,7 +596,7 @@ C_process(const char * app, const char * cmdlin, const char ** env,
 	    char* pb = (char*)envblk;
 	    for (p = env; *p; ++p)
 	    {
-		strcpy(pb, *p);
+		C_strlcpy(pb, *p, len+1);
 		pb += strlen(*p) + 1;
 	    }
 	    *pb = '\0';
@@ -1190,36 +1166,6 @@ EOF
       fd) ) )
 
 
-;;; Environment access:
-
-(define setenv
-  (lambda (var val)
-    (##sys#check-string var 'setenv)
-    (##sys#check-string val 'setenv)
-    (##core#inline "C_setenv" (##sys#make-c-string var 'setenv) (##sys#make-c-string val 'setenv))
-    (##core#undefined) ) )
-
-(define (unsetenv var)
-  (##sys#check-string var 'unsetenv)
-  ;; Windows does not support unsetenv, but it can be faked with setenv to ""
-  (##core#inline "C_setenv"
-                 (##sys#make-c-string var 'setenv)
-                 (##sys#make-c-string ""))
-  (##core#undefined) )
-
-(define get-environment-variables
-  (let ([get (foreign-lambda c-string "C_getenventry" int)])
-    (lambda ()
-      (let loop ([i 0])
-	(let ([entry (get i)])
-	  (if entry
-	      (let scan ([j 0])
-		(if (char=? #\= (##core#inline "C_subchar" entry j))
-		    (cons (cons (substring entry 0 j) (substring entry (fx+ j 1) (##sys#size entry))) (loop (fx+ i 1)))
-		    (scan (fx+ j 1)) ) )
-	      '() ) ) ) ) ) )
-
-
 ;;; Time related things:
 
 (define local-timezone-abbreviation
diff --git a/runtime.c b/runtime.c
index 732edc39..9575d800 100644
--- a/runtime.c
+++ b/runtime.c
@@ -602,14 +602,15 @@ void parse_argv(C_char *cmds)
 
     for(bptr0 = bptr = buffer; !isspace((int)(*ptr)) && *ptr != '\0'; *(bptr++) = *(ptr++))
       ++n;
-    
+
     *bptr = '\0';
-    aptr = (C_char *)malloc(sizeof(C_char) * (n + 1));
-    
-    if(aptr == NULL)
+
+    aptr = (C_char*) malloc(sizeof(C_char) * (n + 1));
+    if (!aptr)
       panic(C_text("cannot allocate argument buffer"));
 
-    C_strcpy(aptr, bptr0);
+    C_strlcpy(aptr, bptr0, sizeof(C_char) * (n + 1));
+
     C_main_argv[ C_main_argc++ ] = aptr;
   }
 }
@@ -1520,7 +1521,7 @@ void usual_panic(C_char *msg)
   C_dbg_hook(C_SCHEME_UNDEFINED);
 
   if(C_gui_mode) {
-    C_sprintf(buffer, C_text("%s\n\n%s"), msg, dmp);
+    C_snprintf(buffer, sizeof(buffer), C_text("%s\n\n%s"), msg, dmp);
 #if defined(_WIN32) && !defined(__CYGWIN__)
     MessageBox(NULL, buffer, C_text("CHICKEN runtime"), MB_OK | MB_ICONERROR);
     ExitProcess(1);
@@ -1537,7 +1538,7 @@ void horror(C_char *msg)
   C_dbg_hook(C_SCHEME_UNDEFINED);
 
   if(C_gui_mode) {
-    C_sprintf(buffer, C_text("%s"), msg);
+    C_snprintf(buffer, sizeof(buffer), C_text("%s"), msg);
 #if defined(_WIN32) && !defined(__CYGWIN__)
     MessageBox(NULL, buffer, C_text("CHICKEN runtime"), MB_OK | MB_ICONERROR);
     ExitProcess(1);
@@ -2528,7 +2529,7 @@ C_regparm C_word C_fcall C_string2_safe(C_word **ptr, int max, C_char *str)
   len = C_strlen(str);
 
   if(len >= max) {
-    C_sprintf(buffer, C_text("foreign string result exceeded maximum of %d bytes"), max);
+    C_snprintf(buffer, sizeof(buffer), C_text("foreign string result exceeded maximum of %d bytes"), max);
     panic(buffer);
   }
 
@@ -3846,9 +3847,10 @@ C_char *C_dump_trace(int start)
 {
   TRACE_INFO *ptr;
   C_char *result;
-  int i;
+  int i, result_len;
 
-  if((result = (char *)C_malloc(STRING_BUFFER_SIZE)) == NULL)
+  result_len = STRING_BUFFER_SIZE;
+  if((result = (char *)C_malloc(result_len)) == NULL)
     horror(C_text("out of memory - cannot allocate trace-dump buffer"));
 
   *result = '\0';
@@ -3856,7 +3858,7 @@ C_char *C_dump_trace(int start)
   if(trace_buffer_top > trace_buffer || trace_buffer_full) {
     if(trace_buffer_full) {
       i = C_trace_buffer_size;
-      C_strcat(result, C_text("...more...\n"));
+      C_strlcat(result, C_text("...more...\n"), result_len);
     }
     else i = trace_buffer_top - trace_buffer;
 
@@ -3868,14 +3870,16 @@ C_char *C_dump_trace(int start)
       if(ptr >= trace_buffer_limit) ptr = trace_buffer;
 
       if(C_strlen(result) > STRING_BUFFER_SIZE - 32) {
-	if((result = C_realloc(result, C_strlen(result) * 2)) == NULL)
+        result_len = C_strlen(result) * 2;
+        result = C_realloc(result, result_len);
+	if(result == NULL)
 	  horror(C_text("out of memory - cannot reallocate trace-dump buffer"));
       }
 
-      C_strcat(result, ptr->raw);
+      C_strlcat(result, ptr->raw, result_len);
 
-      if(i > 0) C_strcat(result, "\n");
-      else C_strcat(result, " \t<--\n");
+      if(i > 0) C_strlcat(result, "\n", result_len);
+      else C_strlcat(result, " \t<--\n", result_len);
     }
   }
 
@@ -3978,18 +3982,17 @@ C_word C_halt(C_word msg)
   if(C_gui_mode) {
     if(msg != C_SCHEME_FALSE) {
       int n = C_header_size(msg);
-      
+
       if (n >= sizeof(buffer))
 	n = sizeof(buffer) - 1;
-      C_strncpy(buffer, (C_char *)C_data_pointer(msg), n);
-      buffer[ n ] = '\0';
+      C_strlcpy(buffer, (C_char *)C_data_pointer(msg), n);
       /* XXX msg isn't checked for NUL bytes, but we can't barf here either! */
     }
-    else C_strcpy(buffer, C_text("(aborted)"));
+    else C_strlcpy(buffer, C_text("(aborted)"), sizeof(buffer));
 
-    C_strcat(buffer, C_text("\n\n"));
+    C_strlcat(buffer, C_text("\n\n"), sizeof(buffer));
 
-    if(dmp != NULL) C_strcat(buffer, dmp);
+    if(dmp != NULL) C_strlcat(buffer, dmp, sizeof(buffer));
 
 #if defined(_WIN32) && !defined(__CYGWIN__) 
     MessageBox(NULL, buffer, C_text("CHICKEN runtime"), MB_OK | MB_ICONERROR);
@@ -7785,13 +7788,13 @@ void C_ccall C_number_to_string(C_word c, C_word closure, C_word k, C_word num,
 
     switch(radix) {
 #ifdef C_SIXTY_FOUR
-    case 8: C_sprintf(p = buffer + 1, C_text("%llo"), (long long)num); break;
-    case 10: C_sprintf(p = buffer + 1, C_text("%lld"), (long long)num); break;
-    case 16: C_sprintf(p = buffer + 1, C_text("%llx"), (long long)num); break;
+    case 8: C_snprintf(p = buffer + 1, sizeof(buffer) -1 , C_text("%llo"), (long long)num); break;
+    case 10: C_snprintf(p = buffer + 1, sizeof(buffer) - 1, C_text("%lld"), (long long)num); break;
+    case 16: C_snprintf(p = buffer + 1, sizeof(buffer) - 1, C_text("%llx"), (long long)num); break;
 #else
-    case 8: C_sprintf(p = buffer + 1, C_text("%o"), num); break;
-    case 10: C_sprintf(p = buffer + 1, C_text("%d"), num); break;
-    case 16: C_sprintf(p = buffer + 1, C_text("%x"), num); break;
+    case 8: C_snprintf(p = buffer + 1, sizeof(buffer) - 1, C_text("%o"), num); break;
+    case 10: C_snprintf(p = buffer + 1, sizeof(buffer) - 1, C_text("%d"), num); break;
+    case 16: C_snprintf(p = buffer + 1, sizeof(buffer) - 1, C_text("%x"), num); break;
 #endif
     default: 
       p = to_n_nary(num, radix);
@@ -7812,11 +7815,11 @@ void C_ccall C_number_to_string(C_word c, C_word closure, C_word k, C_word num,
 
       switch(radix) {
       case 8:
-	C_sprintf(p = buffer, "%o", (unsigned int)f);
+	C_snprintf(p = buffer, sizeof(buffer), "%o", (unsigned int)f);
 	goto fini;
 
       case 16:
-	C_sprintf(p = buffer, "%x", (unsigned int)f);
+	C_snprintf(p = buffer, sizeof(buffer), "%x", (unsigned int)f);
 	goto fini;
 
       case 10: break;		/* force output of decimal point to retain
@@ -7830,11 +7833,13 @@ void C_ccall C_number_to_string(C_word c, C_word closure, C_word k, C_word num,
     } 
 
     if(C_isnan(f)) {
-      C_strcpy(p = buffer, "+nan.0");
+      C_strlcpy(buffer, C_text("+nan.0"), sizeof(buffer));
+      p = buffer;
       goto fini;
     }
     else if(C_isinf(f)) {
-      C_sprintf(p = buffer, "%cinf.0", f > 0 ? '+' : '-');
+      C_snprintf(buffer, sizeof(buffer), "%cinf.0", f > 0 ? '+' : '-');
+      p = buffer;
       goto fini;
     }
 
@@ -7847,7 +7852,7 @@ void C_ccall C_number_to_string(C_word c, C_word closure, C_word k, C_word num,
 	C_memmove(buffer + 1, buffer, C_strlen(buffer) + 1);
 	*buffer = '+';
       }
-      else if(buffer[ 1 ] != 'i') C_strcat(buffer, C_text(".0")); /* negative infinity? */
+      else if(buffer[ 1 ] != 'i') C_strlcat(buffer, C_text(".0"), sizeof(buffer)); /* negative infinity? */
     }
 
     p = buffer;
@@ -7874,9 +7879,9 @@ C_fixnum_to_string(C_word c, C_word self, C_word k, C_word num)
 
   /*XXX is this necessary? */
 #ifdef C_SIXTY_FOUR
-  C_sprintf(buffer, C_text(LONG_FORMAT_STRING), C_unfix(num));
+  C_snprintf(buffer, sizeof(buffer), C_text(LONG_FORMAT_STRING), C_unfix(num));
 #else
-  C_sprintf(buffer, C_text("%d"), C_unfix(num));
+  C_snprintf(buffer, sizeof(buffer), C_text("%d"), C_unfix(num));
 #endif
   n = C_strlen(buffer);
   a = C_alloc(C_bytestowords(n) + 1);
@@ -8429,16 +8434,18 @@ void dload_2(void *dummy)
   C_char *topname = (C_char *)C_data_pointer(entry);
   C_char *mname = (C_char *)C_data_pointer(name);
   C_char *tmp;
+  int tmp_len = 0;
 
   if((handle = C_dlopen(mname, dlopen_flags)) != NULL) {
     if((p = C_dlsym(handle, topname)) == NULL) {
-      tmp = (C_char *)C_malloc(C_strlen(topname) + 2);
-      
+      tmp_len = C_strlen(topname) + 2;
+      tmp = (C_char *)C_malloc(tmp_len);
+
       if(tmp == NULL)
 	panic(C_text("out of memory - cannot allocate toplevel name string"));
-      
-      C_strcpy(tmp, C_text("_"));
-      C_strcat(tmp, topname);
+
+      C_strlcpy(tmp, C_text("_"), tmp_len);
+      C_strlcat(tmp, topname, tmp_len);
       p = C_dlsym(handle, tmp);
       C_free(tmp);
     }
diff --git a/tcp.scm b/tcp.scm
index df31cdab..400e9445 100644
--- a/tcp.scm
+++ b/tcp.scm
@@ -165,7 +165,7 @@ EOF
     "int len = sizeof(struct sockaddr_in);"
     "if(getsockname(s, (struct sockaddr *)&sa, (socklen_t *)&len) != 0) C_return(NULL);"
     "ptr = (unsigned char *)&sa.sin_addr;"
-    "sprintf(addr_buffer, \"%d.%d.%d.%d\", ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ]);"
+    "snprintf(addr_buffer, sizeof(addr_buffer), \"%d.%d.%d.%d\", ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ]);"
     "C_return(addr_buffer);") )
 
 (define ##net#getsockport
@@ -189,7 +189,7 @@ EOF
     "unsigned int len = sizeof(struct sockaddr_in);"
     "if(getpeername(s, (struct sockaddr *)&sa, ((socklen_t *)&len)) != 0) C_return(NULL);"
     "ptr = (unsigned char *)&sa.sin_addr;"
-    "sprintf(addr_buffer, \"%d.%d.%d.%d\", ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ]);"
+    "snprintf(addr_buffer, sizeof(addr_buffer), \"%d.%d.%d.%d\", ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ]);"
     "C_return(addr_buffer);") )
 
 (define ##net#startup
Trap