From c21e976cad6bb90165802df2e4bf5a589bb66617 Mon Sep 17 00:00:00 2001 From: radare Date: Sat, 21 Mar 2020 06:37:58 +0100 Subject: [PATCH] builtin: do not use unsafe sprintf/vsprintf functions --- vlib/builtin/builtin.v | 25 --------- vlib/compiler/live.v | 63 ++++++++++++++------- vlib/compiler/tests/live_test.v | 97 +++++++++++++++++++++++++++++++++ vlib/time/parse.v | 2 +- 4 files changed, 140 insertions(+), 47 deletions(-) create mode 100755 vlib/compiler/tests/live_test.v diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 3a3caee268..da37a4f3ae 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -195,28 +195,3 @@ pub fn is_atty(fd int) int { return C.isatty(fd) } } - -/* -fn C.va_start() -fn C.va_end() -fn C.vsnprintf() int -fn C.vsprintf() int - -pub fn str2_(fmt charptr, ...) string { - argptr := C.va_list{} - C.va_start(argptr, fmt) - len := C.vsnprintf(0, 0, fmt, argptr) + 1 -C.va_end(argptr) - buf := malloc(len) - C.va_start(argptr, fmt) - C.vsprintf(charptr(buf), fmt, argptr) - C.va_end(argptr) -//#ifdef DEBUG_ALLOC -// puts("_STR:"); -// puts(buf); -//#endif - return tos2(buf) -} -*/ - - diff --git a/vlib/compiler/live.v b/vlib/compiler/live.v index a80e3ea455..9747dda876 100644 --- a/vlib/compiler/live.v +++ b/vlib/compiler/live.v @@ -110,24 +110,35 @@ fn (v &V) generate_hot_reload_code() { cgen.genln(' void lfnmutex_print(char *s){ - if(0){ - fflush(stderr); - fprintf(stderr,">> live_fn_mutex: %p | %s\\n", &live_fn_mutex, s); - fflush(stderr); - } +#if 0 + fflush(stderr); + fprintf(stderr,">> live_fn_mutex: %p | %s\\n", &live_fn_mutex, s); + fflush(stderr); +#endif } ') if v.pref.os != .windows { cgen.genln(' -void* live_lib=0; +#define _POSIX_C_SOURCE 1 +#include +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +void* live_lib = 0; + int load_so(byteptr path) { - char cpath[1024]; - sprintf(cpath,"./%s", path); + char cpath[PATH_MAX] = {0}; + int res = snprintf(cpath, sizeof (cpath), "./%s", path); + if (res >= sizeof (cpath)) { + fprintf (stderr, "path is too long"); + return 0; + } //printf("load_so %s\\n", cpath); if (live_lib) dlclose(live_lib); live_lib = dlopen(cpath, RTLD_LAZY); if (!live_lib) { - puts("open failed"); + fprintf(stderr, "open failed"); exit(1); return 0; } @@ -138,6 +149,11 @@ int load_so(byteptr path) { } else { cgen.genln(' + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + void pthread_mutex_lock(HANDLE *m) { WaitForSingleObject(*m, INFINITE); } @@ -146,14 +162,19 @@ void pthread_mutex_unlock(HANDLE *m) { ReleaseMutex(*m); } -void* live_lib=0; +void* live_lib = NULL; int load_so(byteptr path) { - char cpath[1024]; - sprintf(cpath, "./%s", path); + char cpath[PATH_MAX]; + int res = snprintf(cpath, sizeof (cpath), "./%s", path); + if (res >= sizeof(cpath)) { + puts("path is too long\\n"); + exit(1); + return 0; + } if (live_lib) FreeLibrary(live_lib); live_lib = LoadLibraryA(cpath); if (!live_lib) { - puts("open failed"); + puts("open failed\\n"); exit(1); return 0; } @@ -167,9 +188,9 @@ int load_so(byteptr path) { int _live_reloads = 0; void reload_so() { - char new_so_base[1024]; - char new_so_name[1024]; - char compile_cmd[1024]; + char new_so_base[PATH_MAX] = {0}; + char new_so_name[PATH_MAX] = {0}; + char compile_cmd[PATH_MAX] = {0}; int last = os__file_last_mod_unix(tos2("$file")); while (1) { // TODO use inotify @@ -179,22 +200,22 @@ void reload_so() { _live_reloads++; //v -o bounce -shared bounce.v - sprintf(new_so_base, ".tmp.%d.${file_base}", _live_reloads); + snprintf(new_so_base, sizeof (new_so_base), ".tmp.%d.${file_base}", _live_reloads); #ifdef _WIN32 // We have to make this directory becuase windows WILL NOT // do it for us os__mkdir(string_all_before_last(tos2(new_so_base), tos2("/"))); #endif #ifdef _MSC_VER - sprintf(new_so_name, "%s.dll", new_so_base); + snprintf(new_so_name, sizeof (new_so_name), "%s.dll", new_so_base); #else - sprintf(new_so_name, "%s.so", new_so_base); + snprintf(new_so_name, sizeof (new_so_name), "%s.so", new_so_base); #endif - sprintf(compile_cmd, "$vexe $msvc -o %s -solive -shared $file", new_so_base); + snprintf(compile_cmd, sizeof (compile_cmd), "$vexe $msvc -o %s -solive -shared $file", new_so_base); os__system(tos2(compile_cmd)); if( !os__exists(tos2(new_so_name)) ) { - fprintf(stderr, "Errors while compiling $file\\n"); + puts("Errors while compiling $file\\n"); continue; } diff --git a/vlib/compiler/tests/live_test.v b/vlib/compiler/tests/live_test.v new file mode 100755 index 0000000000..fb9edd5f86 --- /dev/null +++ b/vlib/compiler/tests/live_test.v @@ -0,0 +1,97 @@ +import os +import time + +const ( + vexe = os.getenv('VEXE') + source_file = os.join_path(os.temp_dir(), 'generated_live_program.v') + output_file = os.join_path(os.temp_dir(), 'generated_live_program.output.txt') + live_program_source = " +module main +import time + +[live] +fn pmessage() { + println('ORIGINAL') +} + +fn main() { + println('START') + for i := 0; i<6*100; i++ { + pmessage() + time.sleep_ms(10) + } + println('END') +} +" +) + +// + +fn testsuite_begin(){ + if os.user_os() != 'linux' && os.getenv('FORCE_LIVE_TEST').len == 0 { + eprintln('Testing the runtime behaviour of -live mode,') + eprintln('is reliable only on Linux for now.') + eprintln('You can still do it by setting FORCE_LIVE_TEST=1 .') + exit(0) + } + os.write_file(source_file, live_program_source) +} + +fn testsuite_end(){ + os.rm( source_file ) + eprintln('source: $source_file') + eprintln('output: $output_file') + $if !windows { + os.system('cat $output_file') + } + println('---------------------------------------------------------------------------') + output_lines := os.read_lines( output_file ) or { + return + } + mut histogram := map[string]int + for line in output_lines { + histogram[line] = histogram[line] + 1 + } + for k,v in histogram { + println('> found ${k} $v times.') + } + println('---------------------------------------------------------------------------') + assert histogram['START'] > 0 + assert histogram['END'] > 0 + assert histogram['CHANGED'] + histogram['ANOTHER'] > 0 + assert histogram['ORIGINAL'] > 0 +} + +fn change_source(new string){ + time.sleep_ms(250) + eprintln('> change ORIGINAL to: $new') + os.write_file(source_file,live_program_source.replace('ORIGINAL', new)) + time.sleep_ms(1000) + eprintln('> done.') +} + +// + +fn test_live_program_can_be_compiled(){ + cmd := '$vexe -live run $source_file > $output_file &' + eprintln('Compiling and running with: $cmd') + res := os.system(cmd) + eprintln('... running in the background') + time.sleep_ms(3000) + assert res == 0 +} + +fn test_live_program_can_be_changed_1(){ + change_source('CHANGED') + assert true +} + +fn test_live_program_can_be_changed_2(){ + change_source('ANOTHER') + assert true +} + +fn test_live_program_has_ended(){ + time.sleep_ms(10*1000) + assert true +} diff --git a/vlib/time/parse.v b/vlib/time/parse.v index 06f3b150d2..3ec1955891 100644 --- a/vlib/time/parse.v +++ b/vlib/time/parse.v @@ -42,7 +42,7 @@ pub fn parse_rfc2822(s string) ?Time { mm := pos / 3 + 1 mut tmstr := byteptr(0) unsafe { tmstr = malloc(s.len * 2) } - count := C.sprintf(charptr(tmstr), '%s-%02d-%s %s', fields[3].str, mm, + count := C.snprintf(charptr(tmstr), (s.len * 2), '%s-%02d-%s %s', fields[3].str, mm, fields[1].str, fields[4].str) t := parse(tos(tmstr, count)) or {