Make the utf16 conversion procedures in core:sys/windows safer by checking for memory leaks

This commit is contained in:
gingerBill
2022-05-12 13:17:58 +01:00
parent bb4f108487
commit eef44b11f3
17 changed files with 105 additions and 72 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 {
return
}
path := strings.concatenate({base_path, `\`, win32.utf16_to_utf8(d.cFileName[:])})
path := strings.concatenate({base_path, `\`, win32.utf16_to_utf8(d.cFileName[:]) or_else ""})
fi.fullpath = path
fi.name = basename(path)
fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
+2 -2
View File
@@ -22,7 +22,7 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
}
if n <= u32(len(b)) {
value = win32.utf16_to_utf8(b[:n], allocator)
value, _ = win32.utf16_to_utf8(b[:n], allocator)
found = true
return
}
@@ -76,7 +76,7 @@ environ :: proc(allocator := context.allocator) -> []string {
if i <= from {
break
}
append(&r, win32.utf16_to_utf8(envs[from:i], allocator))
append(&r, win32.utf16_to_utf8(envs[from:i], allocator) or_else "")
from = i + 1
}
}
+1 -1
View File
@@ -365,7 +365,7 @@ get_current_directory :: proc(allocator := context.allocator) -> string {
win32.ReleaseSRWLockExclusive(&cwd_lock)
return win32.utf16_to_utf8(dir_buf_wstr, allocator)
return win32.utf16_to_utf8(dir_buf_wstr, allocator) or_else ""
}
set_current_directory :: proc(path: string) -> (err: Errno) {
+2 -2
View File
@@ -29,7 +29,7 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string
return "", false
}
value = win32.utf16_to_utf8(b[:n], allocator)
value = win32.utf16_to_utf8(b[:n], allocator) or_else ""
found = true
return
}
@@ -73,7 +73,7 @@ _environ :: proc(allocator: runtime.Allocator) -> []string {
break
}
w := ([^]u16)(p)[from:i]
append(&r, win32.utf16_to_utf8(w, allocator))
append(&r, win32.utf16_to_utf8(w, allocator) or_else "")
from = i + 1
}
}
+18
View File
@@ -21,6 +21,7 @@ File_Mode_Device :: File_Mode(1<<18)
File_Mode_Char_Device :: File_Mode(1<<19)
File_Mode_Sym_Link :: File_Mode(1<<20)
File_Mode_Perm :: File_Mode(0o777) // Unix permision bits
File_Flags :: distinct bit_set[File_Flag; uint]
File_Flag :: enum {
@@ -194,3 +195,20 @@ is_dir :: proc(path: string) -> bool {
return _is_dir(path)
}
copy_file :: proc(dst_path, src_path: string) -> Error {
src := open(src_path) or_return
defer close(src)
info := fstat(src, _file_allocator()) or_return
defer file_info_delete(info, _file_allocator())
if info.is_dir {
return .Invalid_File
}
dst := open(dst_path, {.Read, .Write, .Create, .Trunc}, info.mode & File_Mode_Perm) or_return
defer close(dst)
_, err := io.copy(to_writer(dst), to_reader(src))
return err
}
+9 -1
View File
@@ -2,12 +2,20 @@ package os2
import "core:io"
file_to_stream :: proc(f: ^File) -> (s: io.Stream) {
to_stream :: proc(f: ^File) -> (s: io.Stream) {
s.stream_data = f
s.stream_vtable = _file_stream_vtable
return
}
to_writer :: proc(f: ^File) -> (s: io.Writer) {
return {to_stream(f)}
}
to_reader :: proc(f: ^File) -> (s: io.Reader) {
return {to_stream(f)}
}
@(private)
error_to_io_error :: proc(ferr: Error) -> io.Error {
if ferr == nil {
+6 -6
View File
@@ -529,16 +529,16 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st
}
if !has_unc_prefix(p) {
return win32.utf16_to_utf8(p, allocator), nil
return win32.utf16_to_utf8(p, allocator)
}
ws := p[4:]
switch {
case len(ws) >= 2 && ws[1] == ':':
return win32.utf16_to_utf8(ws, allocator), nil
return win32.utf16_to_utf8(ws, allocator)
case has_prefix(ws, `UNC\`):
ws[3] = '\\' // override data in buffer
return win32.utf16_to_utf8(ws[3:], allocator), nil
return win32.utf16_to_utf8(ws[3:], allocator)
}
@@ -560,9 +560,9 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st
ws = ws[4:]
if len(ws) > 3 && has_prefix(ws, `UNC`) {
ws[2] = '\\'
return win32.utf16_to_utf8(ws[2:], allocator), nil
return win32.utf16_to_utf8(ws[2:], allocator)
}
return win32.utf16_to_utf8(ws, allocator), nil
return win32.utf16_to_utf8(ws, allocator)
}
return "", .Invalid_Path
}
@@ -593,7 +593,7 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er
pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0
p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength]
if rb.Flags & win32.SYMLINK_FLAG_RELATIVE != 0 {
return win32.utf16_to_utf8(p, allocator), nil
return win32.utf16_to_utf8(p, allocator)
}
return _normalize_link_path(p, allocator)
+7 -7
View File
@@ -57,7 +57,7 @@ full_path_from_name :: proc(name: string, allocator: runtime.Allocator) -> (path
if n == 0 {
return "", _get_platform_error()
}
return win32.utf16_to_utf8(buf[:n], allocator), nil
return win32.utf16_to_utf8(buf[:n], allocator)
}
@@ -131,7 +131,7 @@ _cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (strin
}
buf := make([]u16, max(n, 260)+1, _temp_allocator())
n = win32.GetFinalPathNameByHandleW(h, raw_data(buf), u32(len(buf)), 0)
return _cleanpath_from_buf(buf[:n], allocator), nil
return _cleanpath_from_buf(buf[:n], allocator)
}
_cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) {
@@ -149,7 +149,7 @@ _cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) {
return _cleanpath_strip_prefix(buf[:n]), nil
}
_cleanpath_from_buf :: proc(buf: []u16, allocator: runtime.Allocator) -> string {
_cleanpath_from_buf :: proc(buf: []u16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) {
buf := buf
buf = _cleanpath_strip_prefix(buf)
return win32.utf16_to_utf8(buf, allocator)
@@ -194,15 +194,15 @@ file_type_mode :: proc(h: win32.HANDLE) -> File_Mode {
_file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (mode: File_Mode) {
if FileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 {
_file_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (mode: File_Mode) {
if file_attributes & win32.FILE_ATTRIBUTE_READONLY != 0 {
mode |= 0o444
} else {
mode |= 0o666
}
is_sym := false
if FileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
if file_attributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
is_sym = false
} else {
is_sym = ReparseTag == win32.IO_REPARSE_TAG_SYMLINK || ReparseTag == win32.IO_REPARSE_TAG_MOUNT_POINT
@@ -211,7 +211,7 @@ _file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HA
if is_sym {
mode |= File_Mode_Sym_Link
} else {
if FileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 {
if file_attributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 {
mode |= 0o111 | File_Mode_Dir
}
+1 -1
View File
@@ -10,6 +10,6 @@ mkdir_temp :: proc(dir, pattern: string, allocator: runtime.Allocator) -> (strin
return _mkdir_temp(dir, pattern, allocator)
}
temp_dir :: proc(allocator: runtime.Allocator) -> string {
temp_dir :: proc(allocator: runtime.Allocator) -> (string, Error) {
return _temp_dir(allocator)
}
+2 -2
View File
@@ -12,10 +12,10 @@ _mkdir_temp :: proc(dir, pattern: string, allocator: runtime.Allocator) -> (stri
return "", nil
}
_temp_dir :: proc(allocator: runtime.Allocator) -> string {
_temp_dir :: proc(allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) {
n := win32.GetTempPathW(0, nil)
if n == 0 {
return ""
return "", nil
}
b := make([]u16, max(win32.MAX_PATH, n), _temp_allocator())
n = win32.GetTempPathW(u32(len(b)), raw_data(b))
+3 -3
View File
@@ -20,7 +20,7 @@ full_path_from_name :: proc(name: string, allocator := context.allocator) -> (pa
return "", Errno(win32.GetLastError())
}
if n <= u32(len(buf)) {
return win32.utf16_to_utf8(buf[:n], allocator), ERROR_NONE
return win32.utf16_to_utf8(buf[:n], allocator) or_else "", ERROR_NONE
}
resize(&buf, len(buf)*2)
}
@@ -136,7 +136,7 @@ cleanpath_from_handle :: proc(fd: Handle) -> (string, Errno) {
if err != 0 {
return "", err
}
return win32.utf16_to_utf8(buf, context.allocator), err
return win32.utf16_to_utf8(buf, context.allocator) or_else "", err
}
@(private)
cleanpath_from_handle_u16 :: proc(fd: Handle) -> ([]u16, Errno) {
@@ -157,7 +157,7 @@ cleanpath_from_handle_u16 :: proc(fd: Handle) -> ([]u16, Errno) {
cleanpath_from_buf :: proc(buf: []u16) -> string {
buf := buf
buf = cleanpath_strip_prefix(buf)
return win32.utf16_to_utf8(buf, context.allocator)
return win32.utf16_to_utf8(buf, context.allocator) or_else ""
}
@(private)