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
|
||||
for i in 0 .. cmd.flags.len {
|
||||
unsafe {
|
||||
mut flag := &cmd.flags[i]
|
||||
if flag.matches(cmd.args, cmd.flags.have_abbrev()) {
|
||||
found = true
|
||||
|
@ -158,6 +159,7 @@ fn (mut cmd Command) parse_flags() {
|
|||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
println('Command `$cmd.name` has no flag `${cmd.args[0]}`')
|
||||
|
|
|
@ -16,8 +16,8 @@ pub fn any_overlap(x, y []byte) bool {
|
|||
return x.len > 0 && y.len > 0 &&
|
||||
// &x.data[0] <= &y.data[y.len-1] &&
|
||||
// &y.data[0] <= &x.data[x.len-1]
|
||||
&x[0] <= &y[y.len-1] &&
|
||||
&y[0] <= &x[x.len-1]
|
||||
unsafe { &x[0] <= &y[y.len-1] &&
|
||||
&y[0] <= &x[x.len-1] }
|
||||
}
|
||||
|
||||
// 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
|
||||
// AEAD, Block, BlockMode and Stream interfaces.
|
||||
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 any_overlap(x, y)
|
||||
|
|
|
@ -1346,7 +1346,7 @@ pub fn (re RE) get_query() string {
|
|||
|
||||
mut i := 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
|
||||
|
||||
// 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++
|
||||
}
|
||||
*/
|
||||
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) {
|
||||
|
|
|
@ -190,7 +190,9 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
|
|||
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) {
|
||||
|
|
|
@ -514,9 +514,13 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
|
|||
}
|
||||
subscr[i].sem = sem
|
||||
subscr[i].prev = &ch.write_subscriber
|
||||
subscr[i].nxt = C.atomic_exchange_ptr(&ch.write_subscriber, &subscr[i])
|
||||
unsafe {
|
||||
subscr[i].nxt = C.atomic_exchange_ptr(&ch.write_subscriber, &subscr[i])
|
||||
}
|
||||
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.write_sub_mtx, u16(0))
|
||||
} else {
|
||||
|
@ -526,9 +530,11 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
|
|||
}
|
||||
subscr[i].sem = sem
|
||||
subscr[i].prev = &ch.read_subscriber
|
||||
subscr[i].nxt = C.atomic_exchange_ptr(&ch.read_subscriber, &subscr[i])
|
||||
unsafe {
|
||||
subscr[i].nxt = C.atomic_exchange_ptr(&ch.read_subscriber, &subscr[i])
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import v.table
|
|||
// generic struct instantiations to concrete types
|
||||
pub fn (b &Builder) generic_struct_insts_to_concrete() {
|
||||
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 {
|
||||
info := typ.info as table.GenericStructInst
|
||||
parent := b.table.types[info.parent_idx]
|
||||
|
|
|
@ -123,13 +123,15 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
|||
mut has_main_fn := false
|
||||
mut files_from_main_module := []&ast.File{}
|
||||
for i in 0 .. ast_files.len {
|
||||
file := &ast_files[i]
|
||||
c.check(file)
|
||||
if file.mod.name == 'main' {
|
||||
files_from_main_module << file
|
||||
has_main_mod_file = true
|
||||
if c.check_file_in_main(file) {
|
||||
has_main_fn = true
|
||||
unsafe {
|
||||
file := &ast_files[i]
|
||||
c.check(file)
|
||||
if file.mod.name == 'main' {
|
||||
files_from_main_module << file
|
||||
has_main_mod_file = true
|
||||
if c.check_file_in_main(file) {
|
||||
has_main_fn = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
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()
|
||||
}
|
||||
if node.op == .mul {
|
||||
|
|
|
@ -88,7 +88,9 @@ fn (mut tasks []TaskDescription) run() {
|
|||
if tasks[i].path in m_skip_files {
|
||||
tasks[i].is_skipped = true
|
||||
}
|
||||
work.push(&tasks[i])
|
||||
unsafe {
|
||||
work.push(&tasks[i])
|
||||
}
|
||||
}
|
||||
work.close()
|
||||
for _ in 0 .. vjobs {
|
||||
|
|
|
@ -534,7 +534,7 @@ typedef struct {
|
|||
for typ in g.table.types {
|
||||
match typ.kind {
|
||||
.alias {
|
||||
parent := &g.table.types[typ.parent_idx]
|
||||
parent := unsafe {&g.table.types[typ.parent_idx]}
|
||||
styp := util.no_dots(typ.name)
|
||||
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) }
|
||||
|
|
|
@ -211,7 +211,7 @@ pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
|
|||
if ts.parent_idx == 0 {
|
||||
break
|
||||
}
|
||||
ts = &t.types[ts.parent_idx]
|
||||
ts = unsafe { &t.types[ts.parent_idx] }
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ pub fn (t &Table) struct_find_field(s &TypeSymbol, name string) ?Field {
|
|||
if ts.parent_idx == 0 {
|
||||
break
|
||||
}
|
||||
ts = &t.types[ts.parent_idx]
|
||||
ts = unsafe { &t.types[ts.parent_idx] }
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
|
|||
// println('get_type_symbol $typ')
|
||||
idx := typ.idx()
|
||||
if idx > 0 {
|
||||
return &t.types[idx]
|
||||
return unsafe{ &t.types[idx] }
|
||||
}
|
||||
// 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
|
||||
return t.get_final_type_symbol(alias_info.parent_type)
|
||||
}
|
||||
return &t.types[idx]
|
||||
return unsafe { &t.types[idx] }
|
||||
}
|
||||
// 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() {
|
||||
v := [int(5), 6, 77, 1]
|
||||
mut p := &v[0]
|
||||
unsafe {
|
||||
mut p := &v[0]
|
||||
(*p)++
|
||||
p++ // p now points to v[1]
|
||||
(*p) += 2
|
||||
|
|
Loading…
Reference in New Issue