v/checker.v: disallow pointer arithmetic for InfixExpr outside unsafe {} (#5640)

pull/5644/head
Nick Treleaven 2020-07-03 17:10:10 +01:00 committed by GitHub
parent a2395ff3e8
commit 0b49e4db1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 221 additions and 93 deletions

View File

@ -29,7 +29,7 @@ fn __new_array(mylen int, cap int, elm_size int) array {
fn __new_array_with_default(mylen int, cap int, elm_size int, val voidptr) array { fn __new_array_with_default(mylen int, cap int, elm_size int, val voidptr) array {
cap_ := if cap < mylen { mylen } else { cap } cap_ := if cap < mylen { mylen } else { cap }
arr := array{ mut arr := array{
element_size: elm_size element_size: elm_size
data: vcalloc(cap_ * elm_size) data: vcalloc(cap_ * elm_size)
len: mylen len: mylen
@ -37,7 +37,9 @@ fn __new_array_with_default(mylen int, cap int, elm_size int, val voidptr) array
} }
if val != 0 { if val != 0 {
for i in 0..arr.len { for i in 0..arr.len {
C.memcpy(charptr(arr.data) + i*elm_size, val, elm_size) unsafe {
arr.set_unsafe(i, val)
}
} }
} }
return arr return arr
@ -45,7 +47,7 @@ fn __new_array_with_default(mylen int, cap int, elm_size int, val voidptr) array
fn __new_array_with_array_default(mylen int, cap int, elm_size int, val array) array { fn __new_array_with_array_default(mylen int, cap int, elm_size int, val array) array {
cap_ := if cap < mylen { mylen } else { cap } cap_ := if cap < mylen { mylen } else { cap }
arr := array{ mut arr := array{
element_size: elm_size element_size: elm_size
data: vcalloc(cap_ * elm_size) data: vcalloc(cap_ * elm_size)
len: mylen len: mylen
@ -53,7 +55,9 @@ fn __new_array_with_array_default(mylen int, cap int, elm_size int, val array) a
} }
for i in 0..arr.len { for i in 0..arr.len {
val_clone := val.clone() val_clone := val.clone()
C.memcpy(charptr(arr.data) + i*elm_size, &val_clone, elm_size) unsafe {
arr.set_unsafe(i, &val_clone)
}
} }
return arr return arr
} }
@ -123,9 +127,13 @@ pub fn (a array) repeat(count int) array {
ary := array{} ary := array{}
C.memcpy(&ary, a.data, sizeof(array)) C.memcpy(&ary, a.data, sizeof(array))
ary_clone := ary.clone() ary_clone := ary.clone()
C.memcpy(byteptr(arr.data) + i * a.len * a.element_size, &ary_clone, a.len * a.element_size) unsafe {
C.memcpy(arr.get_unsafe(i * a.len), &ary_clone, a.len * a.element_size)
}
} else { } else {
C.memcpy(byteptr(arr.data) + i * a.len * a.element_size, byteptr(a.data), a.len * a.element_size) unsafe {
C.memcpy(arr.get_unsafe(i * a.len), byteptr(a.data), a.len * a.element_size)
}
} }
} }
return arr return arr
@ -144,9 +152,10 @@ pub fn (mut a array) insert(i int, val voidptr) {
} }
} }
a.ensure_cap(a.len + 1) a.ensure_cap(a.len + 1)
size := a.element_size unsafe {
C.memmove(byteptr(a.data) + (i + 1) * size, byteptr(a.data) + i * size, (a.len - i) * size) C.memmove(a.get_unsafe(i + 1), a.get_unsafe(i), (a.len - i) * a.element_size)
C.memcpy(byteptr(a.data) + i * size, val, size) a.set_unsafe(i, val)
}
a.len++ a.len++
} }
@ -159,8 +168,11 @@ pub fn (mut a array) insert_many(i int, val voidptr, size int) {
} }
a.ensure_cap(a.len + size) a.ensure_cap(a.len + size)
elem_size := a.element_size elem_size := a.element_size
C.memmove(byteptr(a.data) + (i + size) * elem_size, byteptr(a.data) + i * elem_size, (a.len - i) * elem_size) unsafe {
C.memcpy(byteptr(a.data) + i * elem_size, val, size * elem_size) iptr := a.get_unsafe(i)
C.memmove(a.get_unsafe(i + size), iptr, (a.len - i) * elem_size)
C.memcpy(iptr, val, size * elem_size)
}
a.len += size a.len += size
} }
@ -181,10 +193,11 @@ pub fn (mut a array) delete(i int) {
panic('array.delete: index out of range (i == $i, a.len == $a.len)') panic('array.delete: index out of range (i == $i, a.len == $a.len)')
} }
} }
size := a.element_size
// NB: if a is [12,34], a.len = 2, a.delete(0) // NB: if a is [12,34], a.len = 2, a.delete(0)
// should move (2-0-1) elements = 1 element (the 34) forward // should move (2-0-1) elements = 1 element (the 34) forward
C.memmove(byteptr(a.data) + i * size, byteptr(a.data) + (i + 1) * size, (a.len - i - 1) * size) unsafe {
C.memmove(a.get_unsafe(i), a.get_unsafe(i + 1), (a.len - i - 1) * a.element_size)
}
a.len-- a.len--
} }
@ -201,6 +214,14 @@ pub fn (mut a array) trim(index int) {
} }
} }
// we manually inline this for single operations for performance without -prod
[inline] [unsafe_fn]
fn (a array) get_unsafe(i int) voidptr {
unsafe {
return byteptr(a.data) + i * a.element_size
}
}
// Private function. Used to implement array[] operator // Private function. Used to implement array[] operator
fn (a array) get(i int) voidptr { fn (a array) get(i int) voidptr {
$if !no_bounds_checking? { $if !no_bounds_checking? {
@ -208,7 +229,9 @@ fn (a array) get(i int) voidptr {
panic('array.get: index out of range (i == $i, a.len == $a.len)') panic('array.get: index out of range (i == $i, a.len == $a.len)')
} }
} }
unsafe {
return byteptr(a.data) + i * a.element_size return byteptr(a.data) + i * a.element_size
}
} }
// array.first returns the first element of the array // array.first returns the first element of the array
@ -228,7 +251,9 @@ pub fn (a array) last() voidptr {
panic('array.last: array is empty') panic('array.last: array is empty')
} }
} }
unsafe {
return byteptr(a.data) + (a.len - 1) * a.element_size return byteptr(a.data) + (a.len - 1) * a.element_size
}
} }
// array.slice returns an array using the same buffer as original array // array.slice returns an array using the same buffer as original array
@ -248,10 +273,14 @@ fn (a array) slice(start, _end int) array {
panic('array.slice: slice bounds out of range ($start < 0)') panic('array.slice: slice bounds out of range ($start < 0)')
} }
} }
mut data := byteptr(0)
unsafe {
data = byteptr(a.data) + start * a.element_size
}
l := end - start l := end - start
res := array{ res := array{
element_size: a.element_size element_size: a.element_size
data: byteptr(a.data) + start * a.element_size data: data
len: l len: l
cap: l cap: l
} }
@ -276,7 +305,7 @@ pub fn (a &array) clone() array {
if size == 0 { if size == 0 {
size++ size++
} }
arr := array{ mut arr := array{
element_size: a.element_size element_size: a.element_size
data: vcalloc(size) data: vcalloc(size)
len: a.len len: a.len
@ -286,9 +315,9 @@ pub fn (a &array) clone() array {
if a.element_size == sizeof(array) { if a.element_size == sizeof(array) {
for i in 0..a.len { for i in 0..a.len {
ar := array{} ar := array{}
C.memcpy(&ar, byteptr(a.data) + i * a.element_size, sizeof(array)) C.memcpy(&ar, a.get_unsafe(i), sizeof(array))
ar_clone := ar.clone() ar_clone := ar.clone()
C.memcpy(byteptr(arr.data) + i * a.element_size, &ar_clone, a.element_size) arr.set_unsafe(i, &ar_clone)
} }
} else { } else {
C.memcpy(byteptr(arr.data), a.data, a.cap * a.element_size) C.memcpy(byteptr(arr.data), a.data, a.cap * a.element_size)
@ -309,16 +338,28 @@ fn (a &array) slice_clone(start, _end int) array {
panic('array.slice: slice bounds out of range ($start < 0)') panic('array.slice: slice bounds out of range ($start < 0)')
} }
} }
mut data := byteptr(0)
unsafe {
data = byteptr(a.data) + start * a.element_size
}
l := end - start l := end - start
res := array{ res := array{
element_size: a.element_size element_size: a.element_size
data: byteptr(a.data) + start * a.element_size data: data
len: l len: l
cap: l cap: l
} }
return res.clone() return res.clone()
} }
// we manually inline this for single operations for performance without -prod
[inline] [unsafe_fn]
fn (mut a array) set_unsafe(i int, val voidptr) {
unsafe {
C.memcpy(byteptr(a.data) + a.element_size * i, val, a.element_size)
}
}
// Private function. Used to implement assigment to the array element. // Private function. Used to implement assigment to the array element.
fn (mut a array) set(i int, val voidptr) { fn (mut a array) set(i int, val voidptr) {
$if !no_bounds_checking? { $if !no_bounds_checking? {
@ -326,12 +367,16 @@ fn (mut a array) set(i int, val voidptr) {
panic('array.set: index out of range (i == $i, a.len == $a.len)') panic('array.set: index out of range (i == $i, a.len == $a.len)')
} }
} }
unsafe {
C.memcpy(byteptr(a.data) + a.element_size * i, val, a.element_size) C.memcpy(byteptr(a.data) + a.element_size * i, val, a.element_size)
}
} }
fn (mut a array) push(val voidptr) { fn (mut a array) push(val voidptr) {
a.ensure_cap(a.len + 1) a.ensure_cap(a.len + 1)
unsafe {
C.memcpy(byteptr(a.data) + a.element_size * a.len, val, a.element_size) C.memcpy(byteptr(a.data) + a.element_size * a.len, val, a.element_size)
}
a.len++ a.len++
} }
@ -342,11 +387,15 @@ pub fn (mut a3 array) push_many(val voidptr, size int) {
// handle `arr << arr` // handle `arr << arr`
copy := a3.clone() copy := a3.clone()
a3.ensure_cap(a3.len + size) a3.ensure_cap(a3.len + size)
unsafe {
//C.memcpy(a.data, copy.data, copy.element_size * copy.len) //C.memcpy(a.data, copy.data, copy.element_size * copy.len)
C.memcpy(byteptr(a3.data) + a3.element_size * a3.len, copy.data, a3.element_size * size) C.memcpy(a3.get_unsafe(a3.len), copy.data, a3.element_size * size)
}
} else { } else {
a3.ensure_cap(a3.len + size) a3.ensure_cap(a3.len + size)
C.memcpy(byteptr(a3.data) + a3.element_size * a3.len, val, a3.element_size * size) unsafe {
C.memcpy(a3.get_unsafe(a3.len), val, a3.element_size * size)
}
} }
a3.len += size a3.len += size
} }
@ -357,15 +406,16 @@ pub fn (a array) reverse() array {
if a.len < 2 { if a.len < 2 {
return a return a
} }
arr := array{ mut arr := array{
element_size: a.element_size element_size: a.element_size
data: vcalloc(a.cap * a.element_size) data: vcalloc(a.cap * a.element_size)
len: a.len len: a.len
cap: a.cap cap: a.cap
} }
for i in 0..a.len { for i in 0..a.len {
//C.memcpy(arr.data + i * arr.element_size, &a[a.len - 1 - i], arr.element_size) unsafe {
C.memcpy(byteptr(arr.data) + i * arr.element_size, byteptr(a.data) + (a.len - 1 - i) * arr.element_size, arr.element_size) arr.set_unsafe(i, a.get_unsafe(a.len - 1 - i))
}
} }
return arr return arr
} }
@ -591,7 +641,7 @@ pub fn compare_f32(a, b &f32) int {
pub fn (a array) pointers() []voidptr { pub fn (a array) pointers() []voidptr {
mut res := []voidptr{} mut res := []voidptr{}
for i in 0..a.len { for i in 0..a.len {
res << byteptr(a.data) + i * a.element_size res << a.get_unsafe(i)
} }
return res return res
} }

View File

@ -93,7 +93,9 @@ pub fn (nn int) str_l(max int) string {
buf[index] = `-` buf[index] = `-`
} }
unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
}
return tos(buf, (max-index)) return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -139,7 +141,9 @@ pub fn (nn u32) str() string {
index++ index++
} }
unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
}
return tos(buf, (max-index)) return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -186,7 +190,9 @@ pub fn (nn i64) str() string {
buf[index] = `-` buf[index] = `-`
} }
unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
}
return tos(buf, (max-index)) return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -216,7 +222,9 @@ pub fn (nn u64) str() string {
index++ index++
} }
unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
}
return tos(buf, (max-index)) return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }
@ -260,7 +268,9 @@ pub fn (nn byte) hex() string {
//buf[index] = `0` //buf[index] = `0`
index++ index++
unsafe {
return tos(buf + index, (max - index)) return tos(buf + index, (max - index))
}
} }
pub fn (nn i8) hex() string { pub fn (nn i8) hex() string {
@ -287,7 +297,9 @@ pub fn (nn u16) hex() string {
//buf[index] = `0` //buf[index] = `0`
index++ index++
unsafe {
return tos(buf + index, (max - index)) return tos(buf + index, (max - index))
}
} }
pub fn (nn i16) hex() string { pub fn (nn i16) hex() string {
@ -314,7 +326,9 @@ pub fn (nn u32) hex() string {
//buf[index] = `0` //buf[index] = `0`
index++ index++
unsafe {
return tos(buf + index, (max - index)) return tos(buf + index, (max - index))
}
} }
pub fn (nn int) hex() string { pub fn (nn int) hex() string {
@ -345,7 +359,9 @@ pub fn (nn u64) hex() string {
//buf[index] = `0` //buf[index] = `0`
index++ index++
unsafe {
C.memmove(buf,buf+index, (max-index)+1 ) C.memmove(buf,buf+index, (max-index)+1 )
}
return tos(buf, (max-index)) return tos(buf, (max-index))
//return tos(buf + index, (max-index)) //return tos(buf + index, (max-index))
} }

View File

@ -127,7 +127,9 @@ fn (mut d DenseArray) push(key string, value voidptr) u32 {
} }
push_index := d.len push_index := d.len
d.keys[push_index] = key d.keys[push_index] = key
unsafe {
C.memcpy(d.values + push_index * u32(d.value_bytes), value, d.value_bytes) C.memcpy(d.values + push_index * u32(d.value_bytes), value, d.value_bytes)
}
d.len++ d.len++
return push_index return push_index
} }
@ -138,7 +140,9 @@ fn (d DenseArray) get(i int) voidptr {
panic('DenseArray.get: index out of range (i == $i, d.len == $d.len)') panic('DenseArray.get: index out of range (i == $i, d.len == $d.len)')
} }
} }
unsafe {
return byteptr(d.keys) + i * int(sizeof(string)) return byteptr(d.keys) + i * int(sizeof(string))
}
} }
// Move all zeros to the end of the array and resize array // Move all zeros to the end of the array and resize array
@ -152,9 +156,11 @@ fn (mut d DenseArray) zeros_to_end() {
d.keys[count] = d.keys[i] d.keys[count] = d.keys[i]
d.keys[i] = tmp_key d.keys[i] = tmp_key
// swap values (TODO: optimize) // swap values (TODO: optimize)
unsafe {
C.memcpy(tmp_value, d.values + count * u32(d.value_bytes), d.value_bytes) C.memcpy(tmp_value, d.values + count * u32(d.value_bytes), d.value_bytes)
C.memcpy(d.values + count * u32(d.value_bytes), d.values + i * d.value_bytes, d.value_bytes) C.memcpy(d.values + count * u32(d.value_bytes), d.values + i * d.value_bytes, d.value_bytes)
C.memcpy(d.values + i * d.value_bytes, tmp_value, d.value_bytes) C.memcpy(d.values + i * d.value_bytes, tmp_value, d.value_bytes)
}
count++ count++
} }
} }
@ -206,8 +212,10 @@ fn new_map_1(value_bytes int) map {
fn new_map_init(n, value_bytes int, keys &string, values voidptr) map { fn new_map_init(n, value_bytes int, keys &string, values voidptr) map {
mut out := new_map_1(value_bytes) mut out := new_map_1(value_bytes)
for i in 0 .. n { for i in 0 .. n {
unsafe {
out.set(keys[i], byteptr(values) + i * value_bytes) out.set(keys[i], byteptr(values) + i * value_bytes)
} }
}
return out return out
} }
@ -258,8 +266,10 @@ fn (mut m map) ensure_extra_metas(probe_count u32) {
if (probe_count << 1) == m.extra_metas { if (probe_count << 1) == m.extra_metas {
m.extra_metas += extra_metas_inc m.extra_metas += extra_metas_inc
mem_size := (m.cap + 2 + m.extra_metas) mem_size := (m.cap + 2 + m.extra_metas)
unsafe {
m.metas = &u32(C.realloc(m.metas, sizeof(u32) * mem_size)) m.metas = &u32(C.realloc(m.metas, sizeof(u32) * mem_size))
C.memset(m.metas + mem_size - extra_metas_inc, 0, sizeof(u32) * extra_metas_inc) C.memset(m.metas + mem_size - extra_metas_inc, 0, sizeof(u32) * extra_metas_inc)
}
// Should almost never happen // Should almost never happen
if probe_count == 252 { if probe_count == 252 {
panic('Probe overflow') panic('Probe overflow')
@ -282,7 +292,9 @@ fn (mut m map) set(k string, value voidptr) {
for meta == m.metas[index] { for meta == m.metas[index] {
kv_index := m.metas[index + 1] kv_index := m.metas[index + 1]
if fast_string_eq(key, m.key_values.keys[kv_index]) { if fast_string_eq(key, m.key_values.keys[kv_index]) {
unsafe {
C.memcpy(m.key_values.values + kv_index * u32(m.value_bytes), value, m.value_bytes) C.memcpy(m.key_values.values + kv_index * u32(m.value_bytes), value, m.value_bytes)
}
return return
} }
index += 2 index += 2
@ -362,9 +374,11 @@ fn (mut m map) get_and_set(key string, zero voidptr) voidptr {
if meta == m.metas[index] { if meta == m.metas[index] {
kv_index := m.metas[index + 1] kv_index := m.metas[index + 1]
if fast_string_eq(key, m.key_values.keys[kv_index]) { if fast_string_eq(key, m.key_values.keys[kv_index]) {
unsafe {
return voidptr(m.key_values.values + kv_index * u32(m.value_bytes)) return voidptr(m.key_values.values + kv_index * u32(m.value_bytes))
} }
} }
}
index += 2 index += 2
meta += probe_inc meta += probe_inc
if meta > m.metas[index] { break } if meta > m.metas[index] { break }
@ -383,9 +397,11 @@ fn (m map) get(key string, zero voidptr) voidptr {
if meta == m.metas[index] { if meta == m.metas[index] {
kv_index := m.metas[index + 1] kv_index := m.metas[index + 1]
if fast_string_eq(key, m.key_values.keys[kv_index]) { if fast_string_eq(key, m.key_values.keys[kv_index]) {
unsafe {
return voidptr(m.key_values.values + kv_index * u32(m.value_bytes)) return voidptr(m.key_values.values + kv_index * u32(m.value_bytes))
} }
} }
}
index += 2 index += 2
meta += probe_inc meta += probe_inc
if meta > m.metas[index] { break } if meta > m.metas[index] { break }

View File

@ -39,10 +39,10 @@ fn opt_ok2(data voidptr, mut option &OptionBase, size int) {
*option = OptionBase { *option = OptionBase {
ok: true ok: true
} }
}
// use ecode to get the end of OptionBase and then memcpy into it // use ecode to get the end of OptionBase and then memcpy into it
C.memcpy(byteptr(&option.ecode) + sizeof(int), data, size) C.memcpy(byteptr(&option.ecode) + sizeof(int), data, size)
}
} }
// Old option type used for bootstrapping // Old option type used for bootstrapping

View File

@ -48,8 +48,10 @@ fn new_sorted_map(n, value_bytes int) SortedMap { // TODO: Remove `n`
fn new_sorted_map_init(n, value_bytes int, keys &string, values voidptr) SortedMap { fn new_sorted_map_init(n, value_bytes int, keys &string, values voidptr) SortedMap {
mut out := new_sorted_map(n, value_bytes) mut out := new_sorted_map(n, value_bytes)
for i in 0 .. n { for i in 0 .. n {
unsafe {
out.set(keys[i], byteptr(values) + i * value_bytes) out.set(keys[i], byteptr(values) + i * value_bytes)
} }
}
return out return out
} }

View File

@ -118,8 +118,10 @@ pub fn (_str string) to_wide() &u16 {
mut wstr := &u16(malloc((num_chars + 1) * 2)) // sizeof(wchar_t) mut wstr := &u16(malloc((num_chars + 1) * 2)) // sizeof(wchar_t)
if wstr != 0 { if wstr != 0 {
C.MultiByteToWideChar(cp_utf8, 0, _str.str, _str.len, wstr, num_chars) C.MultiByteToWideChar(cp_utf8, 0, _str.str, _str.len, wstr, num_chars)
unsafe {
C.memset(&byte(wstr) + num_chars * 2, 0, 2) C.memset(&byte(wstr) + num_chars * 2, 0, 2)
} }
}
return wstr return wstr
} $else { } $else {
return 0 return 0
@ -141,8 +143,10 @@ pub fn string_from_wide2(_wstr &u16, len int) string {
mut str_to := malloc(num_chars + 1) mut str_to := malloc(num_chars + 1)
if str_to != 0 { if str_to != 0 {
C.WideCharToMultiByte(cp_utf8, 0, _wstr, len, str_to, num_chars, 0, 0) C.WideCharToMultiByte(cp_utf8, 0, _wstr, len, str_to, num_chars, 0, 0)
unsafe {
C.memset(str_to + num_chars, 0, 1) C.memset(str_to + num_chars, 0, 1)
} }
}
return tos2(str_to) return tos2(str_to)
} $else { } $else {
return '' return ''

View File

@ -51,6 +51,7 @@ fn wyhash64(key byteptr, len, seed_ u64) u64 {
mut p := &key[0] mut p := &key[0]
mut seed := seed_ mut seed := seed_
mut i := len & 63 mut i := len & 63
unsafe {
if i < 4 { if i < 4 {
seed = wymum(wyr3(p, i) ^ seed ^ wyp0, seed ^ wyp1) seed = wymum(wyr3(p, i) ^ seed ^ wyp0, seed ^ wyp1)
} }
@ -69,12 +70,14 @@ fn wyhash64(key byteptr, len, seed_ u64) u64 {
else { else {
seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + 8) ^ seed ^ wyp1) ^ wymum(wyr8(p + 16) ^ seed ^ wyp2, wyr8(p + 24) ^ seed ^ wyp3) ^ wymum(wyr8(p + i - 32) ^ seed ^ wyp1, wyr8(p + i - 24) ^ seed ^ wyp2) ^ wymum(wyr8(p + i - 16) ^ seed ^ wyp3, wyr8(p + i - 8) ^ seed ^ wyp0) seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + 8) ^ seed ^ wyp1) ^ wymum(wyr8(p + 16) ^ seed ^ wyp2, wyr8(p + 24) ^ seed ^ wyp3) ^ wymum(wyr8(p + i - 32) ^ seed ^ wyp1, wyr8(p + i - 24) ^ seed ^ wyp2) ^ wymum(wyr8(p + i - 16) ^ seed ^ wyp3, wyr8(p + i - 8) ^ seed ^ wyp0)
} }
}
if i == len { if i == len {
return wymum(seed, len ^ wyp4) return wymum(seed, len ^ wyp4)
} }
mut see1 := seed mut see1 := seed
mut see2 := seed mut see2 := seed
mut see3 := seed mut see3 := seed
unsafe {
p = p + i p = p + i
for i = len - i; i >= 64; i -= 64 { for i = len - i; i >= 64; i -= 64 {
seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + 8) ^ seed ^ wyp1) seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + 8) ^ seed ^ wyp1)
@ -83,6 +86,7 @@ fn wyhash64(key byteptr, len, seed_ u64) u64 {
see3 = wymum(wyr8(p + 48) ^ see3 ^ wyp3, wyr8(p + 56) ^ see3 ^ wyp0) see3 = wymum(wyr8(p + 48) ^ see3 ^ wyp3, wyr8(p + 56) ^ see3 ^ wyp0)
p = p + 64 p = p + 64
} }
}
return wymum(seed ^ see1 ^ see2, see3 ^ len ^ wyp4) return wymum(seed ^ see1 ^ see2, see3 ^ len ^ wyp4)
} }

View File

@ -7,7 +7,10 @@ fn (mut ws Client) read_handshake(seckey string) {
buffer_size := 1 buffer_size := 1
mut buffer := malloc(max_buffer) mut buffer := malloc(max_buffer)
for bytes_read <= max_buffer { for bytes_read <= max_buffer {
res := ws.read_from_server(buffer + bytes_read, buffer_size) mut res := 0
unsafe {
res = ws.read_from_server(buffer + bytes_read, buffer_size)
}
if res == 0 || res == -1 { if res == 0 || res == -1 {
l.f('read_handshake: Failed to read handshake.') l.f('read_handshake: Failed to read handshake.')
} }

View File

@ -257,7 +257,9 @@ pub fn (mut ws Client) write(payload byteptr, payload_len int, code OPCode) int
} else if payload_len > 125 && payload_len <= 0xffff { } else if payload_len > 125 && payload_len <= 0xffff {
len16 := C.htons(payload_len) len16 := C.htons(payload_len)
header[1] = (126 | 0x80) header[1] = (126 | 0x80)
unsafe {
C.memcpy(header.data + 2, &len16, 2) C.memcpy(header.data + 2, &len16, 2)
}
header[4] = masking_key[0] header[4] = masking_key[0]
header[5] = masking_key[1] header[5] = masking_key[1]
header[6] = masking_key[2] header[6] = masking_key[2]
@ -265,7 +267,9 @@ pub fn (mut ws Client) write(payload byteptr, payload_len int, code OPCode) int
} else if payload_len > 0xffff && payload_len <= 0xffffffffffffffff { // 65535 && 18446744073709551615 } else if payload_len > 0xffff && payload_len <= 0xffffffffffffffff { // 65535 && 18446744073709551615
len64 := htonl64(u64(payload_len)) len64 := htonl64(u64(payload_len))
header[1] = (127 | 0x80) header[1] = (127 | 0x80)
unsafe {
C.memcpy(header.data + 2, len64, 8) C.memcpy(header.data + 2, len64, 8)
}
header[10] = masking_key[0] header[10] = masking_key[0]
header[11] = masking_key[1] header[11] = masking_key[1]
header[12] = masking_key[2] header[12] = masking_key[2]
@ -276,8 +280,11 @@ pub fn (mut ws Client) write(payload byteptr, payload_len int, code OPCode) int
goto free_data goto free_data
return -1 return -1
} }
unsafe
{
C.memcpy(fbdata, header.data, header_len) C.memcpy(fbdata, header.data, header_len)
C.memcpy(fbdata + header_len, payload, payload_len) C.memcpy(fbdata + header_len, payload, payload_len)
}
for i in 0 .. payload_len { for i in 0 .. payload_len {
frame_buf[header_len + i] ^= masking_key[i % 4] & 0xff frame_buf[header_len + i] ^= masking_key[i % 4] & 0xff
} }
@ -320,7 +327,10 @@ pub fn (mut ws Client) read() int {
mut frame := Frame{} mut frame := Frame{}
mut frame_size := u64(header_len) mut frame_size := u64(header_len)
for bytes_read < frame_size && ws.state == .open { for bytes_read < frame_size && ws.state == .open {
byt := ws.read_from_server(data + int(bytes_read), 1) mut byt := 0
unsafe {
byt = ws.read_from_server(data + int(bytes_read), 1)
}
match byt { match byt {
0 { 0 {
error := 'server closed the connection.' error := 'server closed the connection.'
@ -442,7 +452,9 @@ pub fn (mut ws Client) read() int {
} }
mut by := 0 mut by := 0
for f in frags { for f in frags {
unsafe {
C.memcpy(pl + by, f.data, f.len) C.memcpy(pl + by, f.data, f.len)
}
by += int(f.len) by += int(f.len)
unsafe { unsafe {
free(f.data) free(f.data)

View File

@ -58,12 +58,16 @@ pub fn environ() map[string]string {
$if windows { $if windows {
mut estrings := C.GetEnvironmentStringsW() mut estrings := C.GetEnvironmentStringsW()
mut eline := '' mut eline := ''
for c := estrings; *c != 0; c = c + eline.len + 1 { for c := estrings; *c != 0; {
eline = string_from_wide(c) eline = string_from_wide(c)
eq_index := eline.index_byte(`=`) eq_index := eline.index_byte(`=`)
if eq_index > 0 { if eq_index > 0 {
res[eline[0..eq_index]] = eline[eq_index + 1..] res[eline[0..eq_index]] = eline[eq_index + 1..]
} }
unsafe
{
c = c + eline.len + 1
}
} }
C.FreeEnvironmentStringsW(estrings) C.FreeEnvironmentStringsW(estrings)
} $else { } $else {

View File

@ -106,12 +106,16 @@ fn close_conn(loop &C.picoev_loop, fd int) {
[inline] [inline]
fn myread(fd int, b byteptr, max_len, idx int) int { fn myread(fd int, b byteptr, max_len, idx int) int {
unsafe {
return C.read(fd, b + idx, max_len - idx) return C.read(fd, b + idx, max_len - idx)
}
} }
[inline] [inline]
fn mysubstr(s byteptr, from, len int) string { fn mysubstr(s byteptr, from, len int) string {
unsafe {
return tos(s + from, len) return tos(s + from, len)
}
} }
fn rw_callback(loop &C.picoev_loop, fd, events int, cb_arg voidptr) { fn rw_callback(loop &C.picoev_loop, fd, events int, cb_arg voidptr) {
@ -123,7 +127,10 @@ fn rw_callback(loop &C.picoev_loop, fd, events int, cb_arg voidptr) {
} }
else if (events & C.PICOEV_READ) != 0 { else if (events & C.PICOEV_READ) != 0 {
C.picoev_set_timeout(loop, fd, timeout_secs) C.picoev_set_timeout(loop, fd, timeout_secs)
buf := (p.buf + fd * max_read) mut buf := p.buf
unsafe {
buf += fd * max_read
}
idx := p.idx[fd] idx := p.idx[fd]
mut r := myread(fd, buf, max_read, idx) mut r := myread(fd, buf, max_read, idx)
if r == 0 { if r == 0 {
@ -141,12 +148,18 @@ fn rw_callback(loop &C.picoev_loop, fd, events int, cb_arg voidptr) {
} else { } else {
r += idx r += idx
mut s := tos(buf, r) mut s := tos(buf, r)
out := (p.out + fd * max_write) mut out := p.out
unsafe {
out += fd * max_write
}
mut res := picohttpparser.Response{ mut res := picohttpparser.Response{
fd: fd fd: fd
date: p.date date: p.date
buf_start: out buf_start: out
buf: out + p.oidx[fd] buf: out
}
unsafe {
res.buf += p.oidx[fd]
} }
mut req := picohttpparser.Request{} mut req := picohttpparser.Request{}
for { for {

View File

@ -477,6 +477,10 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
left_default := c.table.get_type_symbol(c.table.mktyp(left_type)) left_default := c.table.get_type_symbol(c.table.mktyp(left_type))
left_pos := infix_expr.left.position() left_pos := infix_expr.left.position()
right_pos := infix_expr.right.position() right_pos := infix_expr.right.position()
if (left_type.is_ptr() || left.is_pointer()) &&
infix_expr.op in [.plus, .minus] && !c.inside_unsafe {
c.error('pointer arithmetic is only allowed in `unsafe` blocks', left_pos)
}
mut return_type := left_type mut return_type := left_type
// Single side check // Single side check
// Place these branches according to ops' usage frequency to accelerate. // Place these branches according to ops' usage frequency to accelerate.

View File

@ -4,13 +4,13 @@ fn test_ptr_arithmetic(){
unsafe { unsafe {
p++ p++
p += 2 p += 2
p = p - 1
} }
p = p - 1 // not caught yet
// byteptr, voidptr, charptr are handled differently // byteptr, voidptr, charptr are handled differently
mut q := byteptr(1) mut q := byteptr(1)
unsafe { unsafe {
q -= 2 q -= 2
q = q + 1
} }
q = q + 1 // not caught yet
} }