checker: disallow address of array and map index outside unsafe (#6557)
parent
2b1a5d7a56
commit
5f07b255bd
|
@ -148,6 +148,7 @@ fn (mut cmd Command) parse_flags() {
|
||||||
}
|
}
|
||||||
mut found := false
|
mut found := false
|
||||||
for i in 0 .. cmd.flags.len {
|
for i in 0 .. cmd.flags.len {
|
||||||
|
unsafe {
|
||||||
mut flag := &cmd.flags[i]
|
mut flag := &cmd.flags[i]
|
||||||
if flag.matches(cmd.args, cmd.flags.have_abbrev()) {
|
if flag.matches(cmd.args, cmd.flags.have_abbrev()) {
|
||||||
found = true
|
found = true
|
||||||
|
@ -159,6 +160,7 @@ fn (mut cmd Command) parse_flags() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if !found {
|
if !found {
|
||||||
println('Command `$cmd.name` has no flag `${cmd.args[0]}`')
|
println('Command `$cmd.name` has no flag `${cmd.args[0]}`')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
|
@ -16,8 +16,8 @@ pub fn any_overlap(x, y []byte) bool {
|
||||||
return x.len > 0 && y.len > 0 &&
|
return x.len > 0 && y.len > 0 &&
|
||||||
// &x.data[0] <= &y.data[y.len-1] &&
|
// &x.data[0] <= &y.data[y.len-1] &&
|
||||||
// &y.data[0] <= &x.data[x.len-1]
|
// &y.data[0] <= &x.data[x.len-1]
|
||||||
&x[0] <= &y[y.len-1] &&
|
unsafe { &x[0] <= &y[y.len-1] &&
|
||||||
&y[0] <= &x[x.len-1]
|
&y[0] <= &x[x.len-1] }
|
||||||
}
|
}
|
||||||
|
|
||||||
// inexact_overlap reports whether x and y share memory at any non-corresponding
|
// inexact_overlap reports whether x and y share memory at any non-corresponding
|
||||||
|
@ -27,7 +27,7 @@ pub fn any_overlap(x, y []byte) bool {
|
||||||
// inexact_overlap can be used to implement the requirements of the crypto/cipher
|
// inexact_overlap can be used to implement the requirements of the crypto/cipher
|
||||||
// AEAD, Block, BlockMode and Stream interfaces.
|
// AEAD, Block, BlockMode and Stream interfaces.
|
||||||
pub fn inexact_overlap(x, y []byte) bool {
|
pub fn inexact_overlap(x, y []byte) bool {
|
||||||
if x.len == 0 || y.len == 0 || &x[0] == &y[0] {
|
if x.len == 0 || y.len == 0 || unsafe { &x[0] == &y[0] } {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return any_overlap(x, y)
|
return any_overlap(x, y)
|
||||||
|
|
|
@ -1346,7 +1346,7 @@ pub fn (re RE) get_query() string {
|
||||||
|
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for i < re.prog.len && re.prog[i].ist != ist_prog_end && re.prog[i].ist != 0{
|
for i < re.prog.len && re.prog[i].ist != ist_prog_end && re.prog[i].ist != 0{
|
||||||
tk := &re.prog[i]
|
tk := unsafe { &re.prog[i] }
|
||||||
ch := tk.ist
|
ch := tk.ist
|
||||||
|
|
||||||
// GROUP start
|
// GROUP start
|
||||||
|
|
|
@ -160,7 +160,9 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string
|
||||||
x++
|
x++
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return tos(byteptr(&buf[0]), i)
|
return unsafe {
|
||||||
|
tos(byteptr(&buf[0]), i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f32_to_decimal_exact_int(i_mant u32, exp u32) (Dec32,bool) {
|
fn f32_to_decimal_exact_int(i_mant u32, exp u32) (Dec32,bool) {
|
||||||
|
|
|
@ -190,7 +190,9 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
|
||||||
x++
|
x++
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return tos(byteptr(&buf[0]), i)
|
return unsafe {
|
||||||
|
tos(byteptr(&buf[0]), i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f64_to_decimal_exact_int(i_mant u64, exp u64) (Dec64, bool) {
|
fn f64_to_decimal_exact_int(i_mant u64, exp u64) (Dec64, bool) {
|
||||||
|
|
|
@ -514,10 +514,14 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
|
||||||
}
|
}
|
||||||
subscr[i].sem = sem
|
subscr[i].sem = sem
|
||||||
subscr[i].prev = &ch.write_subscriber
|
subscr[i].prev = &ch.write_subscriber
|
||||||
|
unsafe {
|
||||||
subscr[i].nxt = C.atomic_exchange_ptr(&ch.write_subscriber, &subscr[i])
|
subscr[i].nxt = C.atomic_exchange_ptr(&ch.write_subscriber, &subscr[i])
|
||||||
|
}
|
||||||
if voidptr(subscr[i].nxt) != voidptr(0) {
|
if voidptr(subscr[i].nxt) != voidptr(0) {
|
||||||
|
unsafe {
|
||||||
subscr[i].nxt.prev = &subscr[i]
|
subscr[i].nxt.prev = &subscr[i]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
C.atomic_store_u16(&ch.write_sub_mtx, u16(0))
|
C.atomic_store_u16(&ch.write_sub_mtx, u16(0))
|
||||||
} else {
|
} else {
|
||||||
mut null16 := u16(0)
|
mut null16 := u16(0)
|
||||||
|
@ -526,9 +530,11 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
|
||||||
}
|
}
|
||||||
subscr[i].sem = sem
|
subscr[i].sem = sem
|
||||||
subscr[i].prev = &ch.read_subscriber
|
subscr[i].prev = &ch.read_subscriber
|
||||||
|
unsafe {
|
||||||
subscr[i].nxt = C.atomic_exchange_ptr(&ch.read_subscriber, &subscr[i])
|
subscr[i].nxt = C.atomic_exchange_ptr(&ch.read_subscriber, &subscr[i])
|
||||||
|
}
|
||||||
if voidptr(subscr[i].nxt) != voidptr(0) {
|
if voidptr(subscr[i].nxt) != voidptr(0) {
|
||||||
subscr[i].nxt.prev = &subscr[i]
|
unsafe { subscr[i].nxt.prev = &subscr[i] }
|
||||||
}
|
}
|
||||||
C.atomic_store_u16(&ch.read_sub_mtx, u16(0))
|
C.atomic_store_u16(&ch.read_sub_mtx, u16(0))
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import v.table
|
||||||
// generic struct instantiations to concrete types
|
// generic struct instantiations to concrete types
|
||||||
pub fn (b &Builder) generic_struct_insts_to_concrete() {
|
pub fn (b &Builder) generic_struct_insts_to_concrete() {
|
||||||
for idx, _ in b.table.types {
|
for idx, _ in b.table.types {
|
||||||
mut typ := &b.table.types[idx]
|
mut typ := unsafe { &b.table.types[idx] }
|
||||||
if typ.kind == .generic_struct_inst {
|
if typ.kind == .generic_struct_inst {
|
||||||
info := typ.info as table.GenericStructInst
|
info := typ.info as table.GenericStructInst
|
||||||
parent := b.table.types[info.parent_idx]
|
parent := b.table.types[info.parent_idx]
|
||||||
|
|
|
@ -123,6 +123,7 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||||
mut has_main_fn := false
|
mut has_main_fn := false
|
||||||
mut files_from_main_module := []&ast.File{}
|
mut files_from_main_module := []&ast.File{}
|
||||||
for i in 0 .. ast_files.len {
|
for i in 0 .. ast_files.len {
|
||||||
|
unsafe {
|
||||||
file := &ast_files[i]
|
file := &ast_files[i]
|
||||||
c.check(file)
|
c.check(file)
|
||||||
if file.mod.name == 'main' {
|
if file.mod.name == 'main' {
|
||||||
|
@ -133,6 +134,7 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if has_main_mod_file && !has_main_fn && files_from_main_module.len > 0 {
|
if has_main_mod_file && !has_main_fn && files_from_main_module.len > 0 {
|
||||||
if c.pref.is_script && !c.pref.is_test {
|
if c.pref.is_script && !c.pref.is_test {
|
||||||
mut first_main_file := files_from_main_module[0]
|
mut first_main_file := files_from_main_module[0]
|
||||||
|
@ -2746,6 +2748,19 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
if node.right is ast.StringLiteral || node.right is ast.StringInterLiteral {
|
if node.right is ast.StringLiteral || node.right is ast.StringInterLiteral {
|
||||||
c.error('cannot take the address of a string', node.pos)
|
c.error('cannot take the address of a string', node.pos)
|
||||||
}
|
}
|
||||||
|
if node.right is ast.IndexExpr as index {
|
||||||
|
typ_sym := c.table.get_type_symbol(index.left_type)
|
||||||
|
if !c.inside_unsafe {
|
||||||
|
if typ_sym.kind == .map {
|
||||||
|
c.error('cannot get address of map values outside unsafe blocks',
|
||||||
|
index.pos)
|
||||||
|
}
|
||||||
|
if typ_sym.kind == .array {
|
||||||
|
c.error('cannot get address of array elements outside unsafe blocks',
|
||||||
|
index.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return right_type.to_ptr()
|
return right_type.to_ptr()
|
||||||
}
|
}
|
||||||
if node.op == .mul {
|
if node.op == .mul {
|
||||||
|
|
|
@ -88,8 +88,10 @@ fn (mut tasks []TaskDescription) run() {
|
||||||
if tasks[i].path in m_skip_files {
|
if tasks[i].path in m_skip_files {
|
||||||
tasks[i].is_skipped = true
|
tasks[i].is_skipped = true
|
||||||
}
|
}
|
||||||
|
unsafe {
|
||||||
work.push(&tasks[i])
|
work.push(&tasks[i])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
work.close()
|
work.close()
|
||||||
for _ in 0 .. vjobs {
|
for _ in 0 .. vjobs {
|
||||||
go work_processor(mut work, mut results)
|
go work_processor(mut work, mut results)
|
||||||
|
|
|
@ -534,7 +534,7 @@ typedef struct {
|
||||||
for typ in g.table.types {
|
for typ in g.table.types {
|
||||||
match typ.kind {
|
match typ.kind {
|
||||||
.alias {
|
.alias {
|
||||||
parent := &g.table.types[typ.parent_idx]
|
parent := unsafe {&g.table.types[typ.parent_idx]}
|
||||||
styp := util.no_dots(typ.name)
|
styp := util.no_dots(typ.name)
|
||||||
is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.`
|
is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.`
|
||||||
parent_styp := if is_c_parent { 'struct ' + util.no_dots(parent.name[2..]) } else { util.no_dots(parent.name) }
|
parent_styp := if is_c_parent { 'struct ' + util.no_dots(parent.name[2..]) } else { util.no_dots(parent.name) }
|
||||||
|
|
|
@ -211,7 +211,7 @@ pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
|
||||||
if ts.parent_idx == 0 {
|
if ts.parent_idx == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ts = &t.types[ts.parent_idx]
|
ts = unsafe { &t.types[ts.parent_idx] }
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ pub fn (t &Table) struct_find_field(s &TypeSymbol, name string) ?Field {
|
||||||
if ts.parent_idx == 0 {
|
if ts.parent_idx == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ts = &t.types[ts.parent_idx]
|
ts = unsafe { &t.types[ts.parent_idx] }
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
|
||||||
// println('get_type_symbol $typ')
|
// println('get_type_symbol $typ')
|
||||||
idx := typ.idx()
|
idx := typ.idx()
|
||||||
if idx > 0 {
|
if idx > 0 {
|
||||||
return &t.types[idx]
|
return unsafe{ &t.types[idx] }
|
||||||
}
|
}
|
||||||
// this should never happen
|
// this should never happen
|
||||||
panic('get_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen')
|
panic('get_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen')
|
||||||
|
@ -310,7 +310,7 @@ pub fn (t &Table) get_final_type_symbol(typ Type) &TypeSymbol {
|
||||||
alias_info := current_type.info as Alias
|
alias_info := current_type.info as Alias
|
||||||
return t.get_final_type_symbol(alias_info.parent_type)
|
return t.get_final_type_symbol(alias_info.parent_type)
|
||||||
}
|
}
|
||||||
return &t.types[idx]
|
return unsafe { &t.types[idx] }
|
||||||
}
|
}
|
||||||
// this should never happen
|
// this should never happen
|
||||||
panic('get_final_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen')
|
panic('get_final_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen')
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
fn test_ptr_assign() {
|
fn test_ptr_assign() {
|
||||||
v := [int(5), 6, 77, 1]
|
v := [int(5), 6, 77, 1]
|
||||||
mut p := &v[0]
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
mut p := &v[0]
|
||||||
(*p)++
|
(*p)++
|
||||||
p++ // p now points to v[1]
|
p++ // p now points to v[1]
|
||||||
(*p) += 2
|
(*p) += 2
|
||||||
|
|
Loading…
Reference in New Issue