>From 09baaefb084622c39de42a87037cefb865a78c7a Mon Sep 17 00:00:00 2001 From: Christian Kellermann Date: Fri, 10 Jan 2014 15:43:07 +0100 Subject: [PATCH] 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 --- Makefile.bsd | 2 ++ chicken.h | 54 ++++++++++++++++++++++++++-------- library.scm | 2 +- posix-common.scm | 61 ++++++++++++++++++++++++++++++++++++++- posixunix.scm | 54 ---------------------------------- posixwin.scm | 68 +++++-------------------------------------- runtime.c | 85 +++++++++++++++++++++++++++++------------------------- tcp.scm | 4 +-- 8 files changed, 160 insertions(+), 170 deletions(-) diff --git a/Makefile.bsd b/Makefile.bsd index 0dbc247..4dd003f 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 bd6c23d..6b8fc6a 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 bf8a194..6194e53 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 d14b4c6..3911b07 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 da0d9f9..224e9b0 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 3dbec6a..b2c3e5c 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 732edc3..9575d80 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 df31cda..400e944 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 -- 1.7.10.4