checker: disallow address of array and map index outside unsafe (#6557)

pull/6568/head
Swastik Baranwal 2020-10-05 16:38:30 +05:30 committed by GitHub
parent 2b1a5d7a56
commit 5f07b255bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 54 additions and 25 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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))
} }

View File

@ -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]

View File

@ -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 {

View File

@ -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)

View File

@ -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) }

View File

@ -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')

View File

@ -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