cgen: fix address violations for `return error(abc)`, reduce leaks in `os`

pull/8102/head
Delyan Angelov 2021-01-14 04:55:30 +02:00
parent a2efb5319d
commit adf084eeed
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
4 changed files with 51 additions and 16 deletions

View File

@ -152,10 +152,11 @@ pub fn rmdir_all(path string) ? {
mut ret_err := '' mut ret_err := ''
items := ls(path) ? items := ls(path) ?
for item in items { for item in items {
if is_dir(join_path(path, item)) { fullpath := join_path(path, item)
rmdir_all(join_path(path, item)) if is_dir(fullpath) {
rmdir_all(fullpath)
} }
rm(join_path(path, item)) or { ret_err = err } rm(fullpath) or { ret_err = err }
} }
rmdir(path) or { ret_err = err } rmdir(path) or { ret_err = err }
if ret_err.len > 0 { if ret_err.len > 0 {
@ -402,13 +403,16 @@ pub fn is_abs_path(path string) bool {
} }
// join_path returns a path as string from input string parameter(s). // join_path returns a path as string from input string parameter(s).
[manualfree]
pub fn join_path(base string, dirs ...string) string { pub fn join_path(base string, dirs ...string) string {
mut result := []string{} mut result := []string{}
result << base.trim_right('\\/') result << base.trim_right('\\/')
for d in dirs { for d in dirs {
result << d result << d
} }
return result.join(path_separator) res := result.join(path_separator)
unsafe { result.free() }
return res
} }
// walk_ext returns a recursive list of all files in `path` ending with `ext`. // walk_ext returns a recursive list of all files in `path` ending with `ext`.
@ -555,13 +559,20 @@ pub fn vmodules_paths() []string {
// See https://discordapp.com/channels/592103645835821068/592294828432424960/630806741373943808 // See https://discordapp.com/channels/592103645835821068/592294828432424960/630806741373943808
// It gives a convenient way to access program resources like images, fonts, sounds and so on, // It gives a convenient way to access program resources like images, fonts, sounds and so on,
// *no matter* how the program was started, and what is the current working directory. // *no matter* how the program was started, and what is the current working directory.
[manualfree]
pub fn resource_abs_path(path string) string { pub fn resource_abs_path(path string) string {
mut base_path := real_path(dir(executable())) exe := executable()
dexe := dir(exe)
mut base_path := real_path(dexe)
vresource := getenv('V_RESOURCE_PATH') vresource := getenv('V_RESOURCE_PATH')
if vresource.len != 0 { if vresource.len != 0 {
base_path = vresource base_path = vresource
} }
return real_path(join_path(base_path, path)) fp := join_path(base_path, path)
res := real_path(fp)
fp.free()
base_path.free()
return res
} }
pub struct Uname { pub struct Uname {

View File

@ -46,6 +46,7 @@ struct C.dirent {
} }
// read_bytes returns all bytes read from file in `path`. // read_bytes returns all bytes read from file in `path`.
[manualfree]
pub fn read_bytes(path string) ?[]byte { pub fn read_bytes(path string) ?[]byte {
mut fp := vfopen(path, 'rb') ? mut fp := vfopen(path, 'rb') ?
cseek := C.fseek(fp, 0, C.SEEK_END) cseek := C.fseek(fp, 0, C.SEEK_END)
@ -63,7 +64,9 @@ pub fn read_bytes(path string) ?[]byte {
return error('fread failed') return error('fread failed')
} }
C.fclose(fp) C.fclose(fp)
return res[0..nr_read_elements * fsize] fres := res[0..nr_read_elements * fsize].clone()
unsafe { res.free() }
return fres
} }
// read_file reads the file in `path` and returns the contents. // read_file reads the file in `path` and returns the contents.
@ -580,15 +583,18 @@ pub fn on_segfault(f voidptr) {
// executable returns the path name of the executable that started the current // executable returns the path name of the executable that started the current
// process. // process.
[manualfree]
pub fn executable() string { pub fn executable() string {
$if linux { $if linux {
mut result := vcalloc(max_path_len) mut xresult := vcalloc(max_path_len)
count := C.readlink('/proc/self/exe', charptr(result), max_path_len) count := C.readlink('/proc/self/exe', charptr(xresult), max_path_len)
if count < 0 { if count < 0 {
eprintln('os.executable() failed at reading /proc/self/exe to get exe path') eprintln('os.executable() failed at reading /proc/self/exe to get exe path')
return executable_fallback() return executable_fallback()
} }
return unsafe { result.vstring() } res := unsafe { xresult.vstring() }.clone()
unsafe { free(xresult) }
return res
} }
$if windows { $if windows {
max := 512 max := 512
@ -713,15 +719,19 @@ pub fn getwd() string {
max := 512 // max_path_len * sizeof(wchar_t) max := 512 // max_path_len * sizeof(wchar_t)
buf := &u16(vcalloc(max * 2)) buf := &u16(vcalloc(max * 2))
if C._wgetcwd(buf, max) == 0 { if C._wgetcwd(buf, max) == 0 {
free(buf)
return '' return ''
} }
return string_from_wide(buf) return string_from_wide(buf)
} $else { } $else {
buf := vcalloc(512) buf := vcalloc(512)
if C.getcwd(charptr(buf), 512) == 0 { if C.getcwd(charptr(buf), 512) == 0 {
free(buf)
return '' return ''
} }
return unsafe { buf.vstring() } res := unsafe { buf.vstring() }.clone()
free(buf)
return res
} }
} }
@ -730,8 +740,12 @@ pub fn getwd() string {
// Also https://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html // Also https://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
// and https://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html // and https://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html
// NB: this particular rabbit hole is *deep* ... // NB: this particular rabbit hole is *deep* ...
[manualfree]
pub fn real_path(fpath string) string { pub fn real_path(fpath string) string {
mut fullpath := vcalloc(max_path_len) mut fullpath := vcalloc(max_path_len)
defer {
unsafe { free(fullpath) }
}
mut ret := charptr(0) mut ret := charptr(0)
$if windows { $if windows {
ret = charptr(C._fullpath(charptr(fullpath), charptr(fpath.str), max_path_len)) ret = charptr(C._fullpath(charptr(fullpath), charptr(fpath.str), max_path_len))
@ -745,7 +759,9 @@ pub fn real_path(fpath string) string {
} }
} }
res := unsafe { fullpath.vstring() } res := unsafe { fullpath.vstring() }
return normalize_drive_letter(res) nres := normalize_drive_letter(res)
cres := nres.clone()
return cres
} }
fn normalize_drive_letter(path string) string { fn normalize_drive_letter(path string) string {

View File

@ -90,10 +90,15 @@ pub fn ls(path string) ?[]string {
if isnil(ent) { if isnil(ent) {
break break
} }
name := tos_clone(byteptr(ent.d_name)) bptr := byteptr(ent.d_name)
if name != '.' && name != '..' && name != '' { unsafe {
res << name if bptr[0] == 0 ||
(bptr[0] == `.` && bptr[1] == 0) ||
(bptr[0] == `.` && bptr[1] == `.` && bptr[2] == 0) {
continue
}
} }
res << tos_clone(bptr)
} }
C.closedir(dir) C.closedir(dir)
return res return res

View File

@ -4160,7 +4160,10 @@ fn (mut g Gen) return_statement(node ast.Return) {
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type) g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
g.writeln(';') g.writeln(';')
styp := g.typ(g.fn_decl.return_type) styp := g.typ(g.fn_decl.return_type)
g.writeln('return *($styp*)&$tmp;') err_obj := g.new_tmp_var()
g.writeln('$styp $err_obj;')
g.writeln('memcpy(&$err_obj, &$tmp, sizeof(Option));')
g.writeln('return $err_obj;')
return return
} }
} }