From ea803113c3052c57e0c7f1607e06318643e436cb Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 14 Feb 2021 18:31:42 +0000 Subject: [PATCH] checker: check `unsafe` V function calls (#8752) --- examples/sokol/cube.v | 8 +++--- examples/sokol/rt_glsl/rt_glsl.v | 9 ++++--- examples/term.ui/text_editor.v | 2 +- examples/ttf_font/example_ttf.v | 2 +- vlib/builtin/array.v | 6 ++--- vlib/builtin/builtin.c.v | 3 +-- vlib/builtin/builtin_nix.c.v | 6 +++-- vlib/builtin/int.v | 10 ++++---- vlib/builtin/map.v | 26 ++++++++++++-------- vlib/builtin/sorted_map.v | 10 ++++---- vlib/builtin/string.v | 25 ++++++++++--------- vlib/builtin/utf8.c.v | 38 +++++++++++++++++------------ vlib/builtin/utf8.v | 7 ++++-- vlib/crypto/rand/rand_linux.c.v | 2 +- vlib/crypto/rand/rand_windows.c.v | 2 +- vlib/encoding/base64/base64.v | 12 ++++++--- vlib/encoding/utf8/utf8_util.v | 8 +++--- vlib/mysql/mysql.v | 8 +++--- vlib/net/http/backend_windows.c.v | 2 +- vlib/net/tcp.v | 2 +- vlib/os/environment.c.v | 26 +++++++++++--------- vlib/os/fd.c.v | 14 +++++------ vlib/os/os.v | 6 +++-- vlib/os/os_c.v | 24 ++++++++++-------- vlib/os/os_nix.c.v | 28 ++++++++++++--------- vlib/picoev/picoev.v | 4 +-- vlib/rand/rand.v | 14 +++++------ vlib/sync/channels.v | 2 +- vlib/term/ui/termios_nix.c.v | 14 ++++++----- vlib/time/parse.v | 11 +++------ vlib/v/checker/checker.v | 4 +-- vlib/vweb/vweb.v | 4 +-- vlib/x/ttf/common.v | 6 +++-- vlib/x/ttf/render_sokol_cpu.v | 8 +++--- vlib/x/websocket/handshake.v | 2 +- vlib/x/websocket/websocket_client.v | 6 ++--- 36 files changed, 200 insertions(+), 161 deletions(-) diff --git a/examples/sokol/cube.v b/examples/sokol/cube.v index a4cea15e8e..ee40fe0763 100644 --- a/examples/sokol/cube.v +++ b/examples/sokol/cube.v @@ -341,7 +341,7 @@ fn my_init(mut app App) { w := 256 h := 256 sz := w * h * 4 - tmp_txt := malloc(sz) + tmp_txt := unsafe {malloc(sz)} mut i := 0 for i < sz { unsafe { @@ -370,8 +370,10 @@ fn my_init(mut app App) { i += 4 } } - app.texture = create_texture(w, h, tmp_txt) - free(tmp_txt) + unsafe { + app.texture = create_texture(w, h, tmp_txt) + free(tmp_txt) + } } fn cleanup(mut app App) { diff --git a/examples/sokol/rt_glsl/rt_glsl.v b/examples/sokol/rt_glsl/rt_glsl.v index f7ae6064f1..c5b2b9e751 100644 --- a/examples/sokol/rt_glsl/rt_glsl.v +++ b/examples/sokol/rt_glsl/rt_glsl.v @@ -331,7 +331,7 @@ fn my_init(mut app App) { w := 256 h := 256 sz := w * h * 4 - tmp_txt := malloc(sz) + tmp_txt := unsafe {malloc(sz)} mut i := 0 for i < sz { unsafe { @@ -360,9 +360,10 @@ fn my_init(mut app App) { i += 4 } } - app.texture = create_texture(w, h, tmp_txt) - free(tmp_txt) - + unsafe { + app.texture = create_texture(w, h, tmp_txt) + free(tmp_txt) + } // glsl init_cube_glsl(mut app) app.init_flag = true diff --git a/examples/term.ui/text_editor.v b/examples/term.ui/text_editor.v index 6a537c293a..74ac41789d 100644 --- a/examples/term.ui/text_editor.v +++ b/examples/term.ui/text_editor.v @@ -300,7 +300,7 @@ fn (mut b Buffer) free() { eprintln(@MOD + '.' + @STRUCT + '::' + @FN) } for line in b.lines { - line.free() + unsafe {line.free()} } unsafe { b.lines.free() } } diff --git a/examples/ttf_font/example_ttf.v b/examples/ttf_font/example_ttf.v index d812984417..8fc696dcfa 100644 --- a/examples/ttf_font/example_ttf.v +++ b/examples/ttf_font/example_ttf.v @@ -145,7 +145,7 @@ fn main() { app.ttf_render << &ttf.TTF_render_Sokol{ bmp: &ttf.BitMap{ tf: &(app.tf[0]) - buf: malloc(32000000) + buf: unsafe {malloc(32000000)} buf_size: (32000000) color: 0xFF0000FF // style: .raw diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 31e35daf69..fead1cccfe 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -98,7 +98,7 @@ fn (mut a array) ensure_cap(required int) { new_size := cap * a.element_size mut new_data := byteptr(0) if a.cap > 0 { - new_data = v_realloc(a.data, new_size) + new_data = unsafe { v_realloc(a.data, new_size) } } else { new_data = vcalloc(new_size) } @@ -274,7 +274,7 @@ pub fn (mut a array) pop() voidptr { a.len = new_len // NB: a.cap is not changed here *on purpose*, so that // further << ops on that array will be more efficient. - return memdup(last_elem, a.element_size) + return unsafe { memdup(last_elem, a.element_size) } } // delete_last efficiently deletes the last element of the array. @@ -507,7 +507,7 @@ pub fn (a []string) str() string { // hex returns a string with the hexadecimal representation // of the byte elements of the array. pub fn (b []byte) hex() string { - mut hex := malloc(b.len * 2 + 1) + mut hex := unsafe { malloc(b.len * 2 + 1) } mut dst_i := 0 for i in b { n0 := i >> 4 diff --git a/vlib/builtin/builtin.c.v b/vlib/builtin/builtin.c.v index 7b9998bd8c..361e97c848 100644 --- a/vlib/builtin/builtin.c.v +++ b/vlib/builtin/builtin.c.v @@ -216,7 +216,6 @@ pub fn v_realloc(b byteptr, n int) byteptr { // v_calloc dynamically allocates a zeroed `n` bytes block of memory on the heap. // v_calloc returns a `byteptr` pointing to the memory address of the allocated space. -[unsafe] pub fn v_calloc(n int) byteptr { return C.calloc(1, n) } @@ -224,7 +223,6 @@ pub fn v_calloc(n int) byteptr { // vcalloc dynamically allocates a zeroed `n` bytes block of memory on the heap. // vcalloc returns a `byteptr` pointing to the memory address of the allocated space. // Unlike `v_calloc` vcalloc checks for negative values given in `n`. -[unsafe] pub fn vcalloc(n int) byteptr { if n < 0 { panic('calloc(<=0)') @@ -246,6 +244,7 @@ pub fn free(ptr voidptr) { // memdup dynamically allocates a `sz` bytes block of memory on the heap // memdup then copies the contents of `src` into the allocated space and // returns a pointer to the newly allocated space. +[unsafe] pub fn memdup(src voidptr, sz int) voidptr { if sz == 0 { return vcalloc(1) diff --git a/vlib/builtin/builtin_nix.c.v b/vlib/builtin/builtin_nix.c.v index ce47656a84..4728ee6199 100644 --- a/vlib/builtin/builtin_nix.c.v +++ b/vlib/builtin/builtin_nix.c.v @@ -116,8 +116,10 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool { } buf := [1000]byte{} mut output := '' - for C.fgets(charptr(buf), 1000, f) != 0 { - output += tos(byteptr(buf), vstrlen(byteptr(buf))) + unsafe { + for C.fgets(charptr(buf), 1000, f) != 0 { + output += tos(byteptr(buf), vstrlen(byteptr(buf))) + } } output = output.trim_space() + ':' if C.pclose(f) != 0 { diff --git a/vlib/builtin/int.v b/vlib/builtin/int.v index 38f2d09e12..5aa2bb00e7 100644 --- a/vlib/builtin/int.v +++ b/vlib/builtin/int.v @@ -65,7 +65,7 @@ fn (nn int) str_l(max int) string { if n == 0 { return '0' } - mut buf := malloc(max + 1) + mut buf := unsafe {malloc(max + 1)} mut is_neg := false if n < 0 { n = -n @@ -136,7 +136,7 @@ pub fn (nn u32) str() string { return '0' } max := 12 - mut buf := malloc(max + 1) + mut buf := unsafe {malloc(max + 1)} mut index := max unsafe { buf[index--] = `\0` @@ -283,7 +283,7 @@ fn u64_to_hex(nn u64, len byte) string { n = n >> 4 } return string{ - str: memdup(buf, len + 1) + str: unsafe {memdup(buf, len + 1)} len: len } } @@ -306,7 +306,7 @@ fn u64_to_hex_no_leading_zeros(nn u64, len byte) string { } res_len := len - i return string{ - str: memdup(&buf[i], res_len + 1) + str: unsafe {memdup(&buf[i], res_len + 1)} len: res_len } } @@ -448,7 +448,7 @@ pub fn (b byte) str() string { // Example: assert byte(97).ascii_str() == 'a' pub fn (b byte) ascii_str() string { mut str := string{ - str: malloc(2) + str: unsafe {malloc(2)} len: 1 } unsafe { diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 82195c53e6..b027853fb7 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -107,7 +107,6 @@ mut: } [inline] -[unsafe] fn new_dense_array(key_bytes int, value_bytes int) DenseArray { slot_bytes := key_bytes + value_bytes cap := 8 @@ -119,7 +118,7 @@ fn new_dense_array(key_bytes int, value_bytes int) DenseArray { len: 0 deletes: 0 all_deleted: 0 - data: malloc(cap * slot_bytes) + data: unsafe { malloc(cap * slot_bytes) } } } @@ -166,7 +165,7 @@ fn (mut d DenseArray) expand() int { // Move all zeros to the end of the array and resize array fn (mut d DenseArray) zeros_to_end() { // TODO alloca? - mut tmp_buf := malloc(d.slot_bytes) + mut tmp_buf := unsafe { malloc(d.slot_bytes) } mut count := 0 for i in 0 .. d.len { if d.has_index(i) { @@ -179,10 +178,12 @@ fn (mut d DenseArray) zeros_to_end() { count++ } } - free(tmp_buf) - d.deletes = 0 - // TODO: reallocate instead as more deletes are likely - free(d.all_deleted) + unsafe { + free(tmp_buf) + d.deletes = 0 + // TODO: reallocate instead as more deletes are likely + free(d.all_deleted) + } d.len = count d.cap = if count < 8 { 8 } else { count } unsafe { @@ -303,7 +304,9 @@ fn map_clone_int_8(dest voidptr, pkey voidptr) { } fn map_free_string(pkey voidptr) { - (*unsafe { &string(pkey) }).free() + unsafe { + (*&string(pkey)).free() + } } fn map_free_nop(_ voidptr) { @@ -617,10 +620,13 @@ fn (mut d DenseArray) delete(i int) { // delete this pub fn (mut m map) delete(key string) { - m.delete_1(&key) + unsafe { + m.delete_1(&key) + } } // Removes the mapping of a particular key from the map. +[unsafe] pub fn (mut m map) delete_1(key voidptr) { mut index, mut meta := m.key_to_index(key) index, meta = m.meta_less(index, meta) @@ -737,7 +743,7 @@ pub fn (m &map) clone() map { cached_hashbits: m.cached_hashbits shift: m.shift key_values: unsafe { m.key_values.clone() } - metas: &u32(malloc(metasize)) + metas: unsafe { &u32(malloc(metasize)) } extra_metas: m.extra_metas len: m.len has_string_keys: m.has_string_keys diff --git a/vlib/builtin/sorted_map.v b/vlib/builtin/sorted_map.v index 9fdd0eab9c..5c492d1183 100644 --- a/vlib/builtin/sorted_map.v +++ b/vlib/builtin/sorted_map.v @@ -106,8 +106,8 @@ fn (mut m SortedMap) set(key string, value voidptr) { j-- } node.keys[j + 1] = key - node.values[j + 1] = malloc(m.value_bytes) unsafe { + node.values[j + 1] = malloc(m.value_bytes) C.memcpy(node.values[j + 1], value, m.value_bytes) } node.len++ @@ -129,17 +129,17 @@ fn (mut n mapnode) split_child(child_index int, mut y mapnode) { z.values[j] = y.values[j + degree] } if !isnil(y.children) { - z.children = &voidptr(malloc(int(children_bytes))) + z.children = unsafe {&voidptr(malloc(int(children_bytes)))} for jj := degree - 1; jj >= 0; jj-- { unsafe { z.children[jj] = y.children[jj + degree] } } } - if isnil(n.children) { - n.children = &voidptr(malloc(int(children_bytes))) - } unsafe { + if isnil(n.children) { + n.children = &voidptr(malloc(int(children_bytes))) + } n.children[n.len + 1] = n.children[n.len] } for j := n.len; j > child_index; j-- { diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 7ed4542ab0..5687f7b222 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -73,7 +73,7 @@ pub fn vstrlen(s byteptr) int { // tos converts a C string to a V string. // String data is reused, not copied. -[unsafe] +//[unsafe] pub fn tos(s byteptr, len int) string { // This should never happen. if s == 0 { @@ -98,7 +98,7 @@ pub fn tos2(s byteptr) string { } return string{ str: s - len: vstrlen(s) + len: unsafe { vstrlen(s) } } } @@ -245,7 +245,7 @@ pub fn (s string) replace(rep string, with string) string { } // Now we know the number of replacements we need to do and we can calc the len of the new string new_len := s.len + idxs.len * (with.len - rep.len) - mut b := malloc(new_len + 1) // add a newline just in case + mut b := unsafe { malloc(new_len + 1) } // add a newline just in case // Fill the new string mut idx_pos := 0 mut cur_idx := idxs[idx_pos] @@ -348,7 +348,7 @@ pub fn (s string) replace_each(vals []string) string { return s } idxs.sort2() - mut b := malloc(new_len + 1) // add a \0 just in case + mut b := unsafe { malloc(new_len + 1) } // add a \0 just in case // Fill the new string mut idx_pos := 0 mut cur_idx := idxs[idx_pos] @@ -491,7 +491,7 @@ fn (s string) ge(a string) bool { fn (s string) add(a string) string { new_len := a.len + s.len mut res := string{ - str: malloc(new_len + 1) + str: unsafe { malloc(new_len + 1) } len: new_len } for j in 0 .. s.len { @@ -608,7 +608,7 @@ pub fn (s string) substr(start int, end int) string { return s.clone() } mut res := string{ - str: malloc(len + 1) + str: unsafe { malloc(len + 1) } len: len } for i in 0 .. len { @@ -1384,6 +1384,7 @@ pub fn (c byte) is_letter() bool { } // free allows for manually freeing the memory occupied by the string +[unsafe] pub fn (s &string) free() { $if prealloc { return @@ -1395,7 +1396,9 @@ pub fn (s &string) free() { if s.is_lit == 1 || s.len == 0 { return } - free(s.str) + unsafe { + free(s.str) + } s.is_lit = -98761234 } @@ -1489,7 +1492,7 @@ pub fn (a []string) join(del string) string { // Allocate enough memory mut res := '' res.len = len - res.str = malloc(res.len + 1) + res.str = unsafe { malloc(res.len + 1) } mut idx := 0 // Go thru every string and copy its every char one by one for i, val in a { @@ -1527,7 +1530,7 @@ pub fn (s string) reverse() string { return s } mut res := string{ - str: malloc(s.len) + str: unsafe { malloc(s.len) } len: s.len } for i := s.len - 1; i >= 0; i-- { @@ -1586,7 +1589,7 @@ pub fn (s string) repeat(count int) string { } else if count == 1 { return s } - mut ret := malloc(s.len * count + 1) + mut ret := unsafe { malloc(s.len * count + 1) } for i in 0 .. count { for j in 0 .. s.len { unsafe { @@ -1635,7 +1638,7 @@ pub fn (s string) strip_margin_custom(del byte) string { } // don't know how much space the resulting string will be, but the max it // can be is this big - mut ret := malloc(s.len + 1) + mut ret := unsafe { malloc(s.len + 1) } mut count := 0 for i := 0; i < s.len; i++ { if s[i] in [`\n`, `\r`] { diff --git a/vlib/builtin/utf8.c.v b/vlib/builtin/utf8.c.v index 8039526e78..a6cc2e3896 100644 --- a/vlib/builtin/utf8.c.v +++ b/vlib/builtin/utf8.c.v @@ -6,14 +6,16 @@ const ( pub fn (_str string) to_wide() &u16 { $if windows { - num_chars := (C.MultiByteToWideChar(cp_utf8, 0, charptr(_str.str), _str.len, 0, - 0)) - mut wstr := &u16(malloc((num_chars + 1) * 2)) // sizeof(wchar_t) - if wstr != 0 { - C.MultiByteToWideChar(cp_utf8, 0, charptr(_str.str), _str.len, wstr, num_chars) - unsafe {C.memset(&byte(wstr) + num_chars * 2, 0, 2)} + unsafe { + num_chars := (C.MultiByteToWideChar(cp_utf8, 0, charptr(_str.str), _str.len, 0, + 0)) + mut wstr := &u16(malloc((num_chars + 1) * 2)) // sizeof(wchar_t) + if wstr != 0 { + C.MultiByteToWideChar(cp_utf8, 0, charptr(_str.str), _str.len, wstr, num_chars) + C.memset(&byte(wstr) + num_chars * 2, 0, 2) + } + return wstr } - return wstr } $else { return 0 } @@ -21,8 +23,10 @@ pub fn (_str string) to_wide() &u16 { pub fn string_from_wide(_wstr &u16) string { $if windows { - wstr_len := C.wcslen(_wstr) - return string_from_wide2(_wstr, wstr_len) + unsafe { + wstr_len := C.wcslen(_wstr) + return string_from_wide2(_wstr, wstr_len) + } } $else { return '' } @@ -30,14 +34,16 @@ pub fn string_from_wide(_wstr &u16) string { pub fn string_from_wide2(_wstr &u16, len int) string { $if windows { - num_chars := C.WideCharToMultiByte(cp_utf8, 0, _wstr, len, 0, 0, 0, 0) - mut str_to := malloc(num_chars + 1) - if str_to != 0 { - C.WideCharToMultiByte(cp_utf8, 0, _wstr, len, charptr(str_to), num_chars, - 0, 0) - unsafe {C.memset(str_to + num_chars, 0, 1)} + unsafe { + num_chars := C.WideCharToMultiByte(cp_utf8, 0, _wstr, len, 0, 0, 0, 0) + mut str_to := malloc(num_chars + 1) + if str_to != 0 { + C.WideCharToMultiByte(cp_utf8, 0, _wstr, len, charptr(str_to), num_chars, + 0, 0) + C.memset(str_to + num_chars, 0, 1) + } + return tos2(str_to) } - return tos2(str_to) } $else { return '' } diff --git a/vlib/builtin/utf8.v b/vlib/builtin/utf8.v index 9ce0ffa05c..6901a2becf 100644 --- a/vlib/builtin/utf8.v +++ b/vlib/builtin/utf8.v @@ -10,10 +10,13 @@ pub fn utf8_char_len(b byte) int { // Convert utf32 to utf8 // utf32 == Codepoint pub fn utf32_to_str(code u32) string { - mut buffer := malloc(5) - return utf32_to_str_no_malloc(code, buffer) + unsafe { + mut buffer := malloc(5) + return utf32_to_str_no_malloc(code, buffer) + } } +[unsafe] pub fn utf32_to_str_no_malloc(code u32, buf voidptr) string { icode := int(code) // Prevents doing casts everywhere mut res := '' diff --git a/vlib/crypto/rand/rand_linux.c.v b/vlib/crypto/rand/rand_linux.c.v index 7bccf4fe5f..fd7dbe1cef 100644 --- a/vlib/crypto/rand/rand_linux.c.v +++ b/vlib/crypto/rand/rand_linux.c.v @@ -25,7 +25,7 @@ pub fn read(bytes_needed int) ?[]byte { } rbytes := getrandom(batch_size, bstart) if rbytes == -1 { - free(buffer) + unsafe { free(buffer) } return read_error } bytes_read += rbytes diff --git a/vlib/crypto/rand/rand_windows.c.v b/vlib/crypto/rand/rand_windows.c.v index 4d68e155de..8059aef548 100644 --- a/vlib/crypto/rand/rand_windows.c.v +++ b/vlib/crypto/rand/rand_windows.c.v @@ -15,7 +15,7 @@ const ( // read returns an array of `bytes_needed` random bytes read from the OS. pub fn read(bytes_needed int) ?[]byte { - mut buffer := malloc(bytes_needed) + mut buffer := unsafe {malloc(bytes_needed)} // use bcrypt_use_system_preferred_rng because we passed null as algo status := C.BCryptGenRandom(0, buffer, bytes_needed, bcrypt_use_system_preferred_rng) if status != status_success { diff --git a/vlib/encoding/base64/base64.v b/vlib/encoding/base64/base64.v index 61586428bf..a7a838ee8a 100644 --- a/vlib/encoding/base64/base64.v +++ b/vlib/encoding/base64/base64.v @@ -21,8 +21,10 @@ pub fn decode(data string) string { if size <= 0 { return '' } - buffer := malloc(size) - return tos(buffer, decode_in_buffer(data, buffer)) + unsafe { + buffer := malloc(size) + return tos(buffer, decode_in_buffer(data, buffer)) + } } // encode encodes the `string` value passed in `data` to base64. @@ -34,8 +36,10 @@ pub fn encode(data string) string { if size <= 0 { return '' } - buffer := malloc(size) - return tos(buffer, encode_in_buffer(data, buffer)) + unsafe { + buffer := malloc(size) + return tos(buffer, encode_in_buffer(data, buffer)) + } } // decode_url returns a decoded URL `string` version of diff --git a/vlib/encoding/utf8/utf8_util.v b/vlib/encoding/utf8/utf8_util.v index 73f444ca58..5479d26627 100644 --- a/vlib/encoding/utf8/utf8_util.v +++ b/vlib/encoding/utf8/utf8_util.v @@ -165,7 +165,7 @@ fn utf8util_char_len(b byte) int { // up_low make the dirt job fn up_low(s string, upper_flag bool) string { mut index := 0 - mut str_res := malloc(s.len + 1) + mut str_res := unsafe {malloc(s.len + 1)} for { ch_len := utf8util_char_len(s[index]) @@ -289,11 +289,9 @@ fn up_low(s string, upper_flag bool) string { // for c compatibility set the ending 0 unsafe { str_res[index] = 0 + //C.printf("str_res: %s\n--------------\n",str_res) + return tos(str_res, s.len) } - - //C.printf("str_res: %s\n--------------\n",str_res) - - return tos(str_res, s.len) } // find_char_in_table utility function for up_low, search utf8 chars in the conversion table diff --git a/vlib/mysql/mysql.v b/vlib/mysql/mysql.v index 3b29d8d408..04346b8b90 100644 --- a/vlib/mysql/mysql.v +++ b/vlib/mysql/mysql.v @@ -125,9 +125,11 @@ pub fn (conn &Connection) tables(wildcard string) ?[]string { // The `s` argument is encoded to produce an escaped SQL string, // taking into account the current character set of the connection. pub fn (conn &Connection) escape_string(s string) string { - to := malloc(2 * s.len + 1) - C.mysql_real_escape_string_quote(conn.conn, to, s.str, s.len, `\'`) - return unsafe { to.vstring() } + unsafe { + to := malloc(2 * s.len + 1) + C.mysql_real_escape_string_quote(conn.conn, to, s.str, s.len, `\'`) + return to.vstring() + } } // set_option - sets extra connect options that affect the behavior of diff --git a/vlib/net/http/backend_windows.c.v b/vlib/net/http/backend_windows.c.v index ee3ab5ebce..b494b825bb 100644 --- a/vlib/net/http/backend_windows.c.v +++ b/vlib/net/http/backend_windows.c.v @@ -11,7 +11,7 @@ fn C.new_tls_context() C.TlsContext fn (req &Request) ssl_do(port int, method Method, host_name string, path string) ?Response { mut ctx := C.new_tls_context() C.vschannel_init(&ctx) - mut buff := malloc(C.vsc_init_resp_buff_size) + mut buff := unsafe {malloc(C.vsc_init_resp_buff_size)} addr := host_name sdata := req.build_request_headers(method, host_name, path) length := int(C.request(&ctx, port, addr.to_wide(), sdata.str, &buff)) diff --git a/vlib/net/tcp.v b/vlib/net/tcp.v index d20bcc87ee..cdb4d09a96 100644 --- a/vlib/net/tcp.v +++ b/vlib/net/tcp.v @@ -161,7 +161,7 @@ pub fn (c &TcpConn) peer_ip() ?string { if cstr == 0 { return error('net.peer_ip: inet_ntop failed') } - res := cstring_to_vstring(cstr) + res := unsafe {cstring_to_vstring(cstr)} return res } diff --git a/vlib/os/environment.c.v b/vlib/os/environment.c.v index 17b29e5d4c..705833b653 100644 --- a/vlib/os/environment.c.v +++ b/vlib/os/environment.c.v @@ -12,19 +12,21 @@ fn C.FreeEnvironmentStringsW(&u16) int // `getenv` returns the value of the environment variable named by the key. pub fn getenv(key string) string { - $if windows { - s := C._wgetenv(key.to_wide()) - if s == 0 { - return '' + unsafe { + $if windows { + s := C._wgetenv(key.to_wide()) + if s == 0 { + return '' + } + return string_from_wide(s) + } $else { + s := C.getenv(charptr(key.str)) + if s == voidptr(0) { + return '' + } + // NB: C.getenv *requires* that the result be copied. + return cstring_to_vstring(byteptr(s)) } - return string_from_wide(s) - } $else { - s := C.getenv(charptr(key.str)) - if s == voidptr(0) { - return '' - } - // NB: C.getenv *requires* that the result be copied. - return cstring_to_vstring(byteptr(s)) } } diff --git a/vlib/os/fd.c.v b/vlib/os/fd.c.v index 7fe9032940..b10abdfec5 100644 --- a/vlib/os/fd.c.v +++ b/vlib/os/fd.c.v @@ -36,14 +36,14 @@ pub fn fd_slurp(fd int) []string { // read from filedescriptor, don't block // return [bytestring,nrbytes] pub fn fd_read(fd int, maxbytes int) (string, int) { - mut buf := malloc(maxbytes) - nbytes := C.read(fd, buf, maxbytes) - if nbytes < 0 { - free(buf) - return '', nbytes - } unsafe { + mut buf := malloc(maxbytes) + nbytes := C.read(fd, buf, maxbytes) + if nbytes < 0 { + free(buf) + return '', nbytes + } buf[nbytes] = 0 + return tos(buf, nbytes), nbytes } - return tos(buf, nbytes), nbytes } diff --git a/vlib/os/os.v b/vlib/os/os.v index d2a6de63a1..db994acca5 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -600,8 +600,10 @@ pub fn resource_abs_path(path string) string { } fp := join_path(base_path, path) res := real_path(fp) - fp.free() - base_path.free() + unsafe { + fp.free() + base_path.free() + } return res } diff --git a/vlib/os/os_c.v b/vlib/os/os_c.v index 82b544d26a..31616091e3 100644 --- a/vlib/os/os_c.v +++ b/vlib/os/os_c.v @@ -715,21 +715,25 @@ pub fn chdir(path string) { pub fn getwd() string { $if windows { max := 512 // max_path_len * sizeof(wchar_t) - buf := &u16(vcalloc(max * 2)) - if C._wgetcwd(buf, max) == 0 { - free(buf) - return '' + unsafe { + buf := &u16(vcalloc(max * 2)) + if C._wgetcwd(buf, max) == 0 { + free(buf) + return '' + } + return string_from_wide(buf) } - return string_from_wide(buf) } $else { buf := vcalloc(512) - if C.getcwd(charptr(buf), 512) == 0 { + unsafe { + if C.getcwd(charptr(buf), 512) == 0 { + free(buf) + return '' + } + res := buf.vstring().clone() free(buf) - return '' + return res } - res := unsafe { buf.vstring() }.clone() - free(buf) - return res } } diff --git a/vlib/os/os_nix.c.v b/vlib/os/os_nix.c.v index 30d4cfa3ce..fde3160424 100644 --- a/vlib/os/os_nix.c.v +++ b/vlib/os/os_nix.c.v @@ -54,16 +54,18 @@ fn C.symlink(charptr, charptr) int pub fn uname() Uname { mut u := Uname{} utsize := sizeof(C.utsname) - x := malloc(int(utsize)) - d := &C.utsname(x) - if C.uname(d) == 0 { - u.sysname = cstring_to_vstring(byteptr(d.sysname)) - u.nodename = cstring_to_vstring(byteptr(d.nodename)) - u.release = cstring_to_vstring(byteptr(d.release)) - u.version = cstring_to_vstring(byteptr(d.version)) - u.machine = cstring_to_vstring(byteptr(d.machine)) + unsafe { + x := malloc(int(utsize)) + d := &C.utsname(x) + if C.uname(d) == 0 { + u.sysname = cstring_to_vstring(byteptr(d.sysname)) + u.nodename = cstring_to_vstring(byteptr(d.nodename)) + u.release = cstring_to_vstring(byteptr(d.release)) + u.version = cstring_to_vstring(byteptr(d.version)) + u.machine = cstring_to_vstring(byteptr(d.machine)) + } + free(d) } - free(d) return u } @@ -166,9 +168,11 @@ pub fn exec(cmd string) ?Result { } buf := [4096]byte{} mut res := strings.new_builder(1024) - for C.fgets(charptr(buf), 4096, f) != 0 { - bufbp := byteptr(buf) - res.write_bytes(bufbp, vstrlen(bufbp)) + unsafe { + for C.fgets(charptr(buf), 4096, f) != 0 { + bufbp := byteptr(buf) + res.write_bytes(bufbp, vstrlen(bufbp)) + } } soutput := res.str() // res.free() diff --git a/vlib/picoev/picoev.v b/vlib/picoev/picoev.v index 866f0229ad..07ba1b9ce8 100644 --- a/vlib/picoev/picoev.v +++ b/vlib/picoev/picoev.v @@ -262,8 +262,8 @@ pub fn new(port int, cb voidptr) &Picoev { loop: loop cb: cb date: C.get_date() - buf: malloc(max_fds * max_read + 1) - out: malloc(max_fds * max_write + 1) + buf: unsafe { malloc(max_fds * max_read + 1) } + out: unsafe { malloc(max_fds * max_write + 1) } } C.picoev_add(loop, fd, C.PICOEV_READ, 0, accept_callback, pv) go update_date(mut pv) diff --git a/vlib/rand/rand.v b/vlib/rand/rand.v index f5a557c556..b2d0f76cc3 100644 --- a/vlib/rand/rand.v +++ b/vlib/rand/rand.v @@ -143,7 +143,7 @@ const ( // string returns a string of length `len` containing random characters in range `[a-zA-Z]`. pub fn string(len int) string { - mut buf := malloc(len) + mut buf := unsafe {malloc(len)} for i in 0 .. len { unsafe { buf[i] = rand.chars[intn(rand.chars.len)] @@ -159,7 +159,7 @@ const ( // hex returns a hexadecimal number of length `len` containing random characters in range `[a-f0-9]`. pub fn hex(len int) string { - mut buf := malloc(len) + mut buf := unsafe {malloc(len)} for i in 0 .. len { unsafe { buf[i] = rand.hex_chars[intn(rand.hex_chars.len)] @@ -174,7 +174,7 @@ const ( // ascii returns a random string of the printable ASCII characters with length `len`. pub fn ascii(len int) string { - mut buf := malloc(len) + mut buf := unsafe {malloc(len)} for i in 0 .. len { unsafe { buf[i] = rand.ascii_chars[intn(rand.ascii_chars.len)] @@ -187,7 +187,7 @@ pub fn ascii(len int) string { // See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random) pub fn uuid_v4() string { buflen := 36 - mut buf := malloc(37) + mut buf := unsafe {malloc(37)} mut i_buf := 0 mut x := u64(0) mut d := byte(0) @@ -219,8 +219,8 @@ pub fn uuid_v4() string { buf[23] = `-` buf[14] = `4` buf[buflen] = 0 + return buf.vstring_with_len(buflen) } - return unsafe { buf.vstring_with_len(buflen) } } const ( @@ -240,7 +240,7 @@ pub fn ulid() string { // ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`. pub fn ulid_at_millisecond(unix_time_milli u64) string { buflen := 26 - mut buf := malloc(27) + mut buf := unsafe {malloc(27)} mut t := unix_time_milli mut i := 9 for i >= 0 { @@ -271,6 +271,6 @@ pub fn ulid_at_millisecond(unix_time_milli u64) string { } unsafe { buf[26] = 0 + return buf.vstring_with_len(buflen) } - return unsafe { buf.vstring_with_len(buflen) } } diff --git a/vlib/sync/channels.v b/vlib/sync/channels.v index 665e24bca4..017a75a74e 100644 --- a/vlib/sync/channels.v +++ b/vlib/sync/channels.v @@ -111,7 +111,7 @@ pub fn new_channel(n u32) &Channel { fn new_channel_st(n u32, st u32) &Channel { wsem := if n > 0 { n } else { 1 } rsem := if n > 0 { u32(0) } else { 1 } - rbuf := if n > 0 { malloc(int(n * st)) } else { byteptr(0) } + rbuf := if n > 0 { unsafe {malloc(int(n * st))} } else { byteptr(0) } sbuf := if n > 0 { vcalloc(int(n * 2)) } else { byteptr(0) } mut ch := &Channel{ objsize: st diff --git a/vlib/term/ui/termios_nix.c.v b/vlib/term/ui/termios_nix.c.v index f612711668..267fc4da05 100644 --- a/vlib/term/ui/termios_nix.c.v +++ b/vlib/term/ui/termios_nix.c.v @@ -164,12 +164,13 @@ fn (mut ctx Context) termios_setup() ? { fn get_cursor_position() (int, int) { print('\033[6n') - buf := malloc(25) - len := C.read(C.STDIN_FILENO, buf, 24) + mut s := '' unsafe { + buf := malloc(25) + len := C.read(C.STDIN_FILENO, buf, 24) buf[len] = 0 + s = tos(buf, len) } - s := tos(buf, len) a := s[2..].split(';') if a.len != 2 { return -1, -1 @@ -186,12 +187,13 @@ fn supports_truecolor() bool { print('\x1b[48:2:1:2:3m') // andquery the current color print('\x1bP\$qm\x1b\\') - buf := malloc(25) - len := C.read(C.STDIN_FILENO, buf, 24) + mut s := '' unsafe { + buf := malloc(25) + len := C.read(C.STDIN_FILENO, buf, 24) buf[len] = 0 + s = tos(buf, len) } - s := tos(buf, len) return '1:2:3' in s } diff --git a/vlib/time/parse.v b/vlib/time/parse.v index 72bcb5931c..411c1b5512 100644 --- a/vlib/time/parse.v +++ b/vlib/time/parse.v @@ -35,15 +35,12 @@ pub fn parse_rfc2822(s string) ?Time { } pos := months_string.index(fields[2]) or { return error('Invalid time format: $s') } mm := pos / 3 + 1 - mut tmstr := byteptr(0) unsafe { - tmstr = malloc(s.len * 2) + tmstr := malloc(s.len * 2) + count := C.snprintf(charptr(tmstr), (s.len * 2), '%s-%02d-%s %s', fields[3].str, + mm, fields[1].str, fields[4].str) + return parse(tos(tmstr, count)) } - count := unsafe { - C.snprintf(charptr(tmstr), (s.len * 2), '%s-%02d-%s %s', fields[3].str, mm, fields[1].str, - fields[4].str) - } - return parse(tos(tmstr, count)) } // ----- iso8601 ----- diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index a1834960ff..2a9d238e55 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1872,8 +1872,8 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { if f.is_deprecated { c.warn('function `$f.name` has been deprecated', call_expr.pos) } - if f.is_unsafe && !c.inside_unsafe && f.language == .c && f.name[2] in [`m`, `s`] - && f.mod == 'builtin' { + if f.is_unsafe && !c.inside_unsafe + && (f.language != .c || (f.name[2] in [`m`, `s`] && f.mod == 'builtin')) { // builtin C.m*, C.s* only - temp c.warn('function `$f.name` must be called from an `unsafe` block', call_expr.pos) } diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index 445be7a935..98708669c2 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -132,7 +132,7 @@ pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bo } s := sb.str() defer { - s.free() + unsafe { s.free() } } send_string(mut ctx.conn, s) or { return false } return true @@ -439,7 +439,7 @@ fn handle_conn(mut conn net.TcpConn, mut app T) { return } app.send_response_to_client(mime_type, data) - data.free() + unsafe { data.free() } return } app.init() diff --git a/vlib/x/ttf/common.v b/vlib/x/ttf/common.v index c05731ea0b..4c91ccf935 100644 --- a/vlib/x/ttf/common.v +++ b/vlib/x/ttf/common.v @@ -87,7 +87,7 @@ fn (mut bmp BitMap) format_texture() { // write out a .ppm file pub fn (mut bmp BitMap) save_as_ppm(file_name string) { tmp_buf := bmp.buf - mut buf := malloc(bmp.buf_size) + mut buf := unsafe {malloc(bmp.buf_size)} unsafe { C.memcpy(buf, tmp_buf, bmp.buf_size) } bmp.buf = buf @@ -108,7 +108,9 @@ pub fn (mut bmp BitMap) save_as_ppm(file_name string) { } f_out.close() - free(buf) + unsafe { + free(buf) + } bmp.buf = tmp_buf } diff --git a/vlib/x/ttf/render_sokol_cpu.v b/vlib/x/ttf/render_sokol_cpu.v index 321385c42d..79c1b976b5 100644 --- a/vlib/x/ttf/render_sokol_cpu.v +++ b/vlib/x/ttf/render_sokol_cpu.v @@ -53,10 +53,10 @@ pub fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32 // RAM buffer if sz > tf_skl.bmp.buf_size { if sz > 0 { - free(tf_skl.bmp.buf) + unsafe {free(tf_skl.bmp.buf)} } dprintln('create_text Alloc: $sz bytes') - tf_skl.bmp.buf = malloc(sz) + tf_skl.bmp.buf = unsafe {malloc(sz)} tf_skl.bmp.buf_size = sz } @@ -91,10 +91,10 @@ pub fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, // RAM buffer if sz > tf_skl.bmp.buf_size { if sz > 0 { - free(tf_skl.bmp.buf) + unsafe {free(tf_skl.bmp.buf)} } dprintln('Alloc: $sz bytes') - tf_skl.bmp.buf = malloc(sz) + tf_skl.bmp.buf = unsafe {malloc(sz)} tf_skl.bmp.buf_size = sz } diff --git a/vlib/x/websocket/handshake.v b/vlib/x/websocket/handshake.v index f351ab17a5..e285124cd4 100644 --- a/vlib/x/websocket/handshake.v +++ b/vlib/x/websocket/handshake.v @@ -25,7 +25,7 @@ fn (mut ws Client) handshake() ? { sb.write('\r\nSec-WebSocket-Version: 13\r\n\r\n') handshake := sb.str() defer { - handshake.free() + unsafe { handshake.free() } } handshake_bytes := handshake.bytes() ws.debug_log('sending handshake: $handshake') diff --git a/vlib/x/websocket/websocket_client.v b/vlib/x/websocket/websocket_client.v index 07f6a4bc57..b19f987212 100644 --- a/vlib/x/websocket/websocket_client.v +++ b/vlib/x/websocket/websocket_client.v @@ -107,7 +107,7 @@ pub fn (mut ws Client) connect() ? { pub fn (mut ws Client) listen() ? { mut log := 'Starting client listener, server($ws.is_server)...' ws.logger.info(log) - log.free() + unsafe { log.free() } defer { ws.logger.info('Quit client listener, server($ws.is_server)...') if ws.state == .open { @@ -131,7 +131,7 @@ pub fn (mut ws Client) listen() ? { .text_frame { log = 'read: text' ws.debug_log(log) - log.free() + unsafe { log.free() } ws.send_message_event(msg) unsafe { msg.free() } } @@ -165,7 +165,7 @@ pub fn (mut ws Client) listen() ? { .close { log = 'read: close' ws.debug_log(log) - log.free() + unsafe { log.free() } defer { ws.manage_clean_close() }