builtin: do not use unsafe sprintf/vsprintf functions

pull/4088/head
radare 2020-03-21 06:37:58 +01:00 committed by GitHub
parent 7e139b5384
commit c21e976cad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 140 additions and 47 deletions

View File

@ -195,28 +195,3 @@ pub fn is_atty(fd int) int {
return C.isatty(fd) 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)
}
*/

View File

@ -110,24 +110,35 @@ fn (v &V) generate_hot_reload_code() {
cgen.genln(' cgen.genln('
void lfnmutex_print(char *s){ void lfnmutex_print(char *s){
if(0){ #if 0
fflush(stderr); fflush(stderr);
fprintf(stderr,">> live_fn_mutex: %p | %s\\n", &live_fn_mutex, s); fprintf(stderr,">> live_fn_mutex: %p | %s\\n", &live_fn_mutex, s);
fflush(stderr); fflush(stderr);
} #endif
} }
') ')
if v.pref.os != .windows { if v.pref.os != .windows {
cgen.genln(' cgen.genln('
void* live_lib=0; #define _POSIX_C_SOURCE 1
#include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
void* live_lib = 0;
int load_so(byteptr path) { int load_so(byteptr path) {
char cpath[1024]; char cpath[PATH_MAX] = {0};
sprintf(cpath,"./%s", path); 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); //printf("load_so %s\\n", cpath);
if (live_lib) dlclose(live_lib); if (live_lib) dlclose(live_lib);
live_lib = dlopen(cpath, RTLD_LAZY); live_lib = dlopen(cpath, RTLD_LAZY);
if (!live_lib) { if (!live_lib) {
puts("open failed"); fprintf(stderr, "open failed");
exit(1); exit(1);
return 0; return 0;
} }
@ -138,6 +149,11 @@ int load_so(byteptr path) {
} }
else { else {
cgen.genln(' cgen.genln('
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
void pthread_mutex_lock(HANDLE *m) { void pthread_mutex_lock(HANDLE *m) {
WaitForSingleObject(*m, INFINITE); WaitForSingleObject(*m, INFINITE);
} }
@ -146,14 +162,19 @@ void pthread_mutex_unlock(HANDLE *m) {
ReleaseMutex(*m); ReleaseMutex(*m);
} }
void* live_lib=0; void* live_lib = NULL;
int load_so(byteptr path) { int load_so(byteptr path) {
char cpath[1024]; char cpath[PATH_MAX];
sprintf(cpath, "./%s", path); 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); if (live_lib) FreeLibrary(live_lib);
live_lib = LoadLibraryA(cpath); live_lib = LoadLibraryA(cpath);
if (!live_lib) { if (!live_lib) {
puts("open failed"); puts("open failed\\n");
exit(1); exit(1);
return 0; return 0;
} }
@ -167,9 +188,9 @@ int load_so(byteptr path) {
int _live_reloads = 0; int _live_reloads = 0;
void reload_so() { void reload_so() {
char new_so_base[1024]; char new_so_base[PATH_MAX] = {0};
char new_so_name[1024]; char new_so_name[PATH_MAX] = {0};
char compile_cmd[1024]; char compile_cmd[PATH_MAX] = {0};
int last = os__file_last_mod_unix(tos2("$file")); int last = os__file_last_mod_unix(tos2("$file"));
while (1) { while (1) {
// TODO use inotify // TODO use inotify
@ -179,22 +200,22 @@ void reload_so() {
_live_reloads++; _live_reloads++;
//v -o bounce -shared bounce.v //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 #ifdef _WIN32
// We have to make this directory becuase windows WILL NOT // We have to make this directory becuase windows WILL NOT
// do it for us // do it for us
os__mkdir(string_all_before_last(tos2(new_so_base), tos2("/"))); os__mkdir(string_all_before_last(tos2(new_so_base), tos2("/")));
#endif #endif
#ifdef _MSC_VER #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 #else
sprintf(new_so_name, "%s.so", new_so_base); snprintf(new_so_name, sizeof (new_so_name), "%s.so", new_so_base);
#endif #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)); os__system(tos2(compile_cmd));
if( !os__exists(tos2(new_so_name)) ) { if( !os__exists(tos2(new_so_name)) ) {
fprintf(stderr, "Errors while compiling $file\\n"); puts("Errors while compiling $file\\n");
continue; continue;
} }

View File

@ -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
}

View File

@ -42,7 +42,7 @@ pub fn parse_rfc2822(s string) ?Time {
mm := pos / 3 + 1 mm := pos / 3 + 1
mut tmstr := byteptr(0) mut tmstr := byteptr(0)
unsafe { tmstr = malloc(s.len * 2) } 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) fields[1].str, fields[4].str)
t := parse(tos(tmstr, count)) or { t := parse(tos(tmstr, count)) or {