mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: do not allow uninitialized function pointers
This commit is contained in:
parent
453137384e
commit
428fd7f57f
@ -18,9 +18,9 @@ pub mut:
|
||||
description string
|
||||
man_description string
|
||||
version string
|
||||
pre_execute FnCommandCallback
|
||||
execute FnCommandCallback
|
||||
post_execute FnCommandCallback
|
||||
pre_execute FnCommandCallback = unsafe { nil }
|
||||
execute FnCommandCallback = unsafe { nil }
|
||||
post_execute FnCommandCallback = unsafe { nil }
|
||||
disable_help bool
|
||||
disable_man bool
|
||||
disable_version bool
|
||||
|
@ -4,13 +4,22 @@ module datatypes
|
||||
|
||||
[heap]
|
||||
struct BloomFilter[T] {
|
||||
hash_func fn (T) u32 // hash function, input [T] , output u32
|
||||
// TODO V bug
|
||||
hash_func fn (T) u32 = unsafe { nil } // hash function, input [T] , output u32
|
||||
// hash_func fn (T) u32 = empty_cb // hash function, input [T] , output u32
|
||||
table_size int // every entry is one-bit, packed into `table`
|
||||
num_functions int // 1~16
|
||||
mut:
|
||||
table []u8
|
||||
}
|
||||
|
||||
/*
|
||||
TODO maybe allow pointing to generic fns?
|
||||
fn empty_cb[T](x T) u32 {
|
||||
panic('empty BloomFilter.hash_func callback')
|
||||
}
|
||||
*/
|
||||
|
||||
const (
|
||||
// Salt values(random values). These salts are XORed with the output of the hash function to give multiple unique hashes.
|
||||
salts = [
|
||||
|
@ -19,7 +19,7 @@ mut:
|
||||
|
||||
struct EventHandler[T] {
|
||||
name T
|
||||
handler EventHandlerFn
|
||||
handler EventHandlerFn = unsafe { nil }
|
||||
receiver voidptr = unsafe { nil }
|
||||
once bool
|
||||
}
|
||||
|
@ -6,15 +6,15 @@ pub struct C.FONSparams {
|
||||
flags char
|
||||
userPtr voidptr
|
||||
// int (*renderCreate)(void* uptr, int width, int height)
|
||||
renderCreate fn (uptr voidptr, width int, height int) int
|
||||
renderCreate fn (uptr voidptr, width int, height int) int = unsafe { nil }
|
||||
// int (*renderResize)(void* uptr, int width, int height)
|
||||
renderResize fn (uptr voidptr, width int, height int) int
|
||||
renderResize fn (uptr voidptr, width int, height int) int = unsafe { nil }
|
||||
// void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data)
|
||||
renderUpdate fn (uptr voidptr, rect &int, data &u8)
|
||||
renderUpdate fn (uptr voidptr, rect &int, data &u8) = unsafe { nil }
|
||||
// void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts)
|
||||
renderDraw fn (uptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int)
|
||||
renderDraw fn (uptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int) = unsafe { nil }
|
||||
// void (*renderDelete)(void* uptr)
|
||||
renderDelete fn (uptr voidptr)
|
||||
renderDelete fn (uptr voidptr) = unsafe { nil }
|
||||
}
|
||||
|
||||
pub struct C.FONSquad {
|
||||
|
@ -248,7 +248,7 @@ mut:
|
||||
// counters for quantifier check (repetitions)
|
||||
rep int
|
||||
// validator function pointer
|
||||
validator FnValidator
|
||||
validator FnValidator = unsafe { nil }
|
||||
// groups variables
|
||||
group_neg bool // negation flag for the group, 0 => no negation > 0 => negataion
|
||||
group_rep int // repetition of the group
|
||||
@ -376,7 +376,7 @@ fn (mut re RE) reset_src() {
|
||||
******************************************************************************/
|
||||
struct BslsStruct {
|
||||
ch rune // meta char
|
||||
validator FnValidator // validator function pointer
|
||||
validator FnValidator = unsafe { nil } // validator function pointer
|
||||
}
|
||||
|
||||
const (
|
||||
@ -463,7 +463,7 @@ mut:
|
||||
cc_type int // type of cc token
|
||||
ch0 rune // first char of the interval a-b a in this case
|
||||
ch1 rune // second char of the interval a-b b in this case
|
||||
validator FnValidator // validator function pointer
|
||||
validator FnValidator = unsafe { nil } // validator function pointer
|
||||
}
|
||||
|
||||
enum CharClass_parse_state {
|
||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
||||
[typedef]
|
||||
pub struct C.sg_allocator {
|
||||
pub mut:
|
||||
alloc memory.FnAllocatorAlloc
|
||||
free memory.FnAllocatorFree
|
||||
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
[typedef]
|
||||
pub struct C.sg_logger {
|
||||
pub mut:
|
||||
log_cb memory.FnLogCb
|
||||
log_cb memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ pub type GLContextDesc = C.sg_gl_context_desc
|
||||
|
||||
struct C.sg_metal_context_desc {
|
||||
device voidptr
|
||||
renderpass_descriptor_cb fn () voidptr
|
||||
drawable_cb fn () voidptr
|
||||
renderpass_descriptor_cb fn () voidptr = unsafe { nil }
|
||||
drawable_cb fn () voidptr = unsafe { nil }
|
||||
}
|
||||
|
||||
pub type MetalContextDesc = C.sg_metal_context_desc
|
||||
@ -55,8 +55,8 @@ pub type MetalContextDesc = C.sg_metal_context_desc
|
||||
struct C.sg_d3d11_context_desc {
|
||||
device voidptr
|
||||
device_context voidptr
|
||||
render_target_view_cb fn () voidptr
|
||||
depth_stencil_view_cb fn () voidptr
|
||||
render_target_view_cb fn () voidptr = unsafe { nil }
|
||||
depth_stencil_view_cb fn () voidptr = unsafe { nil }
|
||||
}
|
||||
|
||||
pub type D3D11ContextDesc = C.sg_d3d11_context_desc
|
||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
||||
[typedef]
|
||||
pub struct C.sapp_allocator {
|
||||
pub mut:
|
||||
alloc memory.FnAllocatorAlloc
|
||||
free memory.FnAllocatorFree
|
||||
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
[typedef]
|
||||
pub struct C.sapp_logger {
|
||||
pub mut:
|
||||
log_cb memory.FnLogCb
|
||||
log_cb memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
@ -37,18 +37,19 @@ pub type IconDesc = C.sapp_icon_desc
|
||||
[typedef]
|
||||
pub struct C.sapp_desc {
|
||||
pub:
|
||||
init_cb fn () // these are the user-provided callbacks without user data
|
||||
frame_cb fn ()
|
||||
cleanup_cb fn ()
|
||||
event_cb fn (&Event) //&sapp_event)
|
||||
fail_cb fn (&u8)
|
||||
// these are the user-provided callbacks without user data
|
||||
init_cb fn () = unsafe { nil }
|
||||
frame_cb fn () = unsafe { nil }
|
||||
cleanup_cb fn () = unsafe { nil }
|
||||
event_cb fn (&Event) = unsafe { nil } // &sapp_event
|
||||
fail_cb fn (&u8) = unsafe { nil }
|
||||
|
||||
user_data voidptr // these are the user-provided callbacks with user data
|
||||
init_userdata_cb fn (voidptr)
|
||||
frame_userdata_cb fn (voidptr)
|
||||
cleanup_userdata_cb fn (voidptr)
|
||||
event_userdata_cb fn (&Event, voidptr)
|
||||
fail_userdata_cb fn (&char, voidptr)
|
||||
init_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
frame_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
cleanup_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
event_userdata_cb fn (&Event, voidptr) = unsafe { nil }
|
||||
fail_userdata_cb fn (&char, voidptr) = unsafe { nil }
|
||||
|
||||
width int // the preferred width of the window / canvas
|
||||
height int // the preferred height of the window / canvas
|
||||
|
@ -6,8 +6,8 @@ import sokol.memory
|
||||
[typedef]
|
||||
pub struct C.sfons_allocator_t {
|
||||
pub:
|
||||
alloc memory.FnAllocatorAlloc
|
||||
free memory.FnAllocatorFree
|
||||
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
||||
[typedef]
|
||||
pub struct C.sgl_allocator_t {
|
||||
pub mut:
|
||||
alloc memory.FnAllocatorAlloc
|
||||
free memory.FnAllocatorFree
|
||||
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
[typedef]
|
||||
pub struct C.sgl_logger_t {
|
||||
pub mut:
|
||||
log_cb memory.FnLogCb
|
||||
log_cb memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
@ -24,9 +24,15 @@ mut:
|
||||
|
||||
pub type ThreadCB = fn (mut p PoolProcessor, idx int, task_id int) voidptr
|
||||
|
||||
fn empty_cb(mut p PoolProcessor, idx int, task_id int) voidptr {
|
||||
unsafe {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PoolProcessorConfig {
|
||||
maxjobs int
|
||||
callback ThreadCB
|
||||
callback ThreadCB = empty_cb
|
||||
}
|
||||
|
||||
// new_pool_processor returns a new PoolProcessor instance.
|
||||
|
@ -15,7 +15,7 @@ pub interface Modifier {
|
||||
pub type InspectorFn = fn (value &ast.Value, data voidptr) !
|
||||
|
||||
struct Inspector {
|
||||
inspector_callback InspectorFn
|
||||
inspector_callback InspectorFn = unsafe { nil }
|
||||
mut:
|
||||
data voidptr
|
||||
}
|
||||
|
@ -10,8 +10,12 @@ mut:
|
||||
|
||||
pub type InspectorFn = fn (node &ast.Node, data voidptr) bool
|
||||
|
||||
fn empty_callback(node &ast.Node, data voidptr) bool {
|
||||
panic('empty ast.walker')
|
||||
}
|
||||
|
||||
struct Inspector {
|
||||
inspector_callback InspectorFn
|
||||
inspector_callback InspectorFn = empty_callback
|
||||
mut:
|
||||
data voidptr
|
||||
}
|
||||
|
@ -70,6 +70,19 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do not allow uninitialized `fn` fields, or force `?fn`
|
||||
// (allow them in `C.` structs)
|
||||
if !c.is_builtin_mod && node.language == .v {
|
||||
sym := c.table.sym(field.typ)
|
||||
if sym.kind == .function {
|
||||
if !field.typ.has_flag(.option) && !field.has_default_expr
|
||||
&& field.attrs.filter(it.name == 'required').len == 0 {
|
||||
error_msg := 'uninitialized `fn` struct fields are not allowed, since they can result in segfaults; use `?fn` or initialize the field with `=` (if you absolutely want to have unsafe function pointers, use `= unsafe { nil }`)'
|
||||
c.note(error_msg, field.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if field.has_default_expr {
|
||||
c.expected_type = field.typ
|
||||
field.default_expr_typ = c.expr(mut field.default_expr)
|
||||
|
@ -1,5 +1,5 @@
|
||||
struct St{
|
||||
attr fn()
|
||||
struct St {
|
||||
attr fn () = unsafe { nil }
|
||||
}
|
||||
|
||||
fn (s St) attr() {}
|
||||
|
@ -1,3 +1,9 @@
|
||||
vlib/v/checker/tests/fn_check_for_matching_option_result_in_fields.vv:2:2: notice: uninitialized `fn` struct fields are not allowed, since they can result in segfaults; use `?fn` or initialize the field with `=` (if you absolutely want to have unsafe function pointers, use `= unsafe { nil }`)
|
||||
1 | struct Abc {
|
||||
2 | f fn (voidptr)
|
||||
| ~~~~~~~~~~~~~~
|
||||
3 | }
|
||||
4 |
|
||||
vlib/v/checker/tests/fn_check_for_matching_option_result_in_fields.vv:7:3: error: cannot assign to field `f`: expected `fn (voidptr)`, not `fn (voidptr) ?`
|
||||
5 | fn main() {
|
||||
6 | a := Abc{
|
||||
|
@ -1,3 +1,10 @@
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:14:2: notice: uninitialized `fn` struct fields are not allowed, since they can result in segfaults; use `?fn` or initialize the field with `=` (if you absolutely want to have unsafe function pointers, use `= unsafe { nil }`)
|
||||
12 |
|
||||
13 | struct FnHolder2[T] {
|
||||
14 | func fn (int) int
|
||||
| ~~~~~~~~~~~~~~~~~
|
||||
15 | }
|
||||
16 |
|
||||
vlib/v/checker/tests/generics_struct_init_err.vv:67:8: error: could not infer generic type `T` in generic struct `FnHolder2[T]`
|
||||
65 | ret = holder_call_22(neg, 5)
|
||||
66 | assert ret == -5
|
||||
|
@ -9,7 +9,7 @@ struct Alarm {
|
||||
struct Clock {
|
||||
mut:
|
||||
arr []Alarm
|
||||
alarm_fkt Fkt
|
||||
alarm_fkt Fkt = unsafe { nil }
|
||||
}
|
||||
|
||||
fn fkt(mut a Alarm) {
|
||||
|
@ -13,7 +13,7 @@ const (
|
||||
)
|
||||
|
||||
struct Data {
|
||||
f fn (int)
|
||||
f fn (int) = unsafe { nil }
|
||||
mut:
|
||||
value int = bar(0)
|
||||
opt ?int = bar(0)
|
||||
|
@ -1,5 +1,5 @@
|
||||
struct App {
|
||||
cb fn(x int) // the function signature doesn't make a difference
|
||||
cb fn(x int) = unsafe { nil } // the function signature doesn't make a difference
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -2,8 +2,8 @@ struct Data {
|
||||
mut:
|
||||
n int
|
||||
b bool
|
||||
f1 fn (voidptr)
|
||||
f2 fn (...voidptr)
|
||||
f1 fn (voidptr) [required]
|
||||
f2 fn (...voidptr) [required]
|
||||
data &Data
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
vlib/v/checker/tests/unknown_type_in_anon_fn.vv:5:10: error: unknown type `Another`
|
||||
3 | struct Struc{
|
||||
4 | mut:
|
||||
5 | f fn (s Another, i int)?
|
||||
5 | f fn (s Another, i int)? [required]
|
||||
| ~~~~~~~
|
||||
6 | }
|
||||
7 |
|
||||
|
@ -2,7 +2,7 @@ module main
|
||||
|
||||
struct Struc{
|
||||
mut:
|
||||
f fn (s Another, i int)?
|
||||
f fn (s Another, i int)? [required]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,9 +1,9 @@
|
||||
module main
|
||||
|
||||
struct Ok {
|
||||
alibaba fn (Ok, )
|
||||
alibaba fn (Ok, ) = unsafe { nil }
|
||||
}
|
||||
|
||||
struct OkInt {
|
||||
a fn (int, )
|
||||
a fn (int, ) = unsafe { nil }
|
||||
}
|
||||
|
@ -446,7 +446,7 @@ type ControllerHandler = fn (ctx Context, mut url urllib.URL, host string, tid i
|
||||
pub struct ControllerPath {
|
||||
pub:
|
||||
path string
|
||||
handler ControllerHandler
|
||||
handler ControllerHandler = unsafe { nil }
|
||||
pub mut:
|
||||
host string
|
||||
}
|
||||
@ -1111,7 +1111,7 @@ fn (mut w Worker[T]) process_incomming_requests() {
|
||||
|
||||
[params]
|
||||
pub struct PoolParams[T] {
|
||||
handler fn () T [required]
|
||||
handler fn () T [required] = unsafe { nil }
|
||||
nr_workers int = runtime.nr_jobs()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user