authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-14 01:09:33-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-14 01:09:33-05:00
log59de24817e8538434f35a20a401f40c2f0231a9a
tree7c06cd2749d2bb449742fc98dac59ab82a480b48
parentd4d2718bca9e23ceec029bb505c0ea1b91c875b6
signaturelock-open Commit is signed but in an unrecognized format.

runtime safety check for casting null to pointer

see #1059

6 files changed, 67 insertions(+), 27 deletions(-)

src/all_types.hpp+3
...@@ -1488,6 +1488,7 @@ enum PanicMsgId {...@@ -1488,6 +1488,7 @@ enum PanicMsgId {
1488 PanicMsgIdBadUnionField,1488 PanicMsgIdBadUnionField,
1489 PanicMsgIdBadEnumValue,1489 PanicMsgIdBadEnumValue,
1490 PanicMsgIdFloatToInt,1490 PanicMsgIdFloatToInt,
1491 PanicMsgIdPtrCastNull,
14911492
1492 PanicMsgIdCount,1493 PanicMsgIdCount,
1493};1494};
...@@ -3001,12 +3002,14 @@ struct IrInstructionPtrCastSrc {...@@ -3001,12 +3002,14 @@ struct IrInstructionPtrCastSrc {
30013002
3002 IrInstruction *dest_type;3003 IrInstruction *dest_type;
3003 IrInstruction *ptr;3004 IrInstruction *ptr;
3005 bool safety_check_on;
3004};3006};
30053007
3006struct IrInstructionPtrCastGen {3008struct IrInstructionPtrCastGen {
3007 IrInstruction base;3009 IrInstruction base;
30083010
3009 IrInstruction *ptr;3011 IrInstruction *ptr;
3012 bool safety_check_on;
3010};3013};
30113014
3012struct IrInstructionBitCast {3015struct IrInstructionBitCast {
src/analyze.cpp+9
...@@ -6902,3 +6902,12 @@ const char *container_string(ContainerKind kind) {...@@ -6902,3 +6902,12 @@ const char *container_string(ContainerKind kind) {
6902 }6902 }
6903 zig_unreachable();6903 zig_unreachable();
6904}6904}
6905
6906bool ptr_allows_addr_zero(ZigType *ptr_type) {
6907 if (ptr_type->id == ZigTypeIdPointer) {
6908 return ptr_type->data.pointer.allow_zero;
6909 } else if (ptr_type->id == ZigTypeIdOptional) {
6910 return true;
6911 }
6912 return false;
6913}
src/analyze.hpp+1
...@@ -45,6 +45,7 @@ void find_libc_lib_path(CodeGen *g);...@@ -45,6 +45,7 @@ void find_libc_lib_path(CodeGen *g);
4545
46bool type_has_bits(ZigType *type_entry);46bool type_has_bits(ZigType *type_entry);
47bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);47bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
48bool ptr_allows_addr_zero(ZigType *ptr_type);
4849
49ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);50ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
5051
src/codegen.cpp+18-1
...@@ -950,6 +950,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {...@@ -950,6 +950,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
950 return buf_create_from_str("invalid enum value");950 return buf_create_from_str("invalid enum value");
951 case PanicMsgIdFloatToInt:951 case PanicMsgIdFloatToInt:
952 return buf_create_from_str("integer part of floating point value out of bounds");952 return buf_create_from_str("integer part of floating point value out of bounds");
953 case PanicMsgIdPtrCastNull:
954 return buf_create_from_str("cast causes pointer to be null");
953 }955 }
954 zig_unreachable();956 zig_unreachable();
955}957}
...@@ -3028,7 +3030,22 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,...@@ -3028,7 +3030,22 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
3028 return nullptr;3030 return nullptr;
3029 }3031 }
3030 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);3032 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3031 return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");3033 LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
3034 bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
3035 if (!want_safety_check || ptr_allows_addr_zero(wanted_type))
3036 return result_ptr;
3037
3038 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr));
3039 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, "");
3040 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail");
3041 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk");
3042 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3043
3044 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3045 gen_safety_crash(g, PanicMsgIdPtrCastNull);
3046
3047 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3048 return result_ptr;
3032}3049}
30333050
3034static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,3051static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
src/ir.cpp+26-26
...@@ -172,7 +172,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -172,7 +172,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
172static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,172static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
173 ConstExprValue *out_val, ConstExprValue *ptr_val);173 ConstExprValue *out_val, ConstExprValue *ptr_val);
174static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,174static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
175 ZigType *dest_type, IrInstruction *dest_type_src);175 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on);
176static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);176static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
177static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);177static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
178static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);178static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
...@@ -2202,12 +2202,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo...@@ -2202,12 +2202,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
2202}2202}
22032203
2204static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,2204static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2205 IrInstruction *dest_type, IrInstruction *ptr)2205 IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on)
2206{2206{
2207 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(2207 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
2208 irb, scope, source_node);2208 irb, scope, source_node);
2209 instruction->dest_type = dest_type;2209 instruction->dest_type = dest_type;
2210 instruction->ptr = ptr;2210 instruction->ptr = ptr;
2211 instruction->safety_check_on = safety_check_on;
22112212
2212 ir_ref_instruction(dest_type, irb->current_basic_block);2213 ir_ref_instruction(dest_type, irb->current_basic_block);
2213 ir_ref_instruction(ptr, irb->current_basic_block);2214 ir_ref_instruction(ptr, irb->current_basic_block);
...@@ -2216,12 +2217,13 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod...@@ -2216,12 +2217,13 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod
2216}2217}
22172218
2218static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,2219static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
2219 ZigType *ptr_type, IrInstruction *ptr)2220 ZigType *ptr_type, IrInstruction *ptr, bool safety_check_on)
2220{2221{
2221 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(2222 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
2222 &ira->new_irb, source_instruction->scope, source_instruction->source_node);2223 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2223 instruction->base.value.type = ptr_type;2224 instruction->base.value.type = ptr_type;
2224 instruction->ptr = ptr;2225 instruction->ptr = ptr;
2226 instruction->safety_check_on = safety_check_on;
22252227
2226 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);2228 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
22272229
...@@ -4505,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4505,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4505 if (arg1_value == irb->codegen->invalid_instruction)4507 if (arg1_value == irb->codegen->invalid_instruction)
4506 return arg1_value;4508 return arg1_value;
45074509
4508 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value);4510 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);
4509 return ir_lval_wrap(irb, scope, ptr_cast, lval);4511 return ir_lval_wrap(irb, scope, ptr_cast, lval);
4510 }4512 }
4511 case BuiltinFnIdBitCast:4513 case BuiltinFnIdBitCast:
...@@ -6740,7 +6742,8 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6740,7 +6742,8 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
6740 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b0106742 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
67416743
6742 // TODO relies on Zig not re-ordering fields6744 // TODO relies on Zig not re-ordering fields
6743 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);6745 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
6746 false);
6744 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6747 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6745 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6748 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6746 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6749 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
...@@ -6818,7 +6821,8 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6818,7 +6821,8 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
6818 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));6821 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
68196822
6820 // TODO relies on Zig not re-ordering fields6823 // TODO relies on Zig not re-ordering fields
6821 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);6824 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
6825 false);
6822 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6826 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6823 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6827 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6824 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6828 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
...@@ -7363,7 +7367,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7363,7 +7367,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
73637367
7364 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,7368 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
7365 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));7369 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
7366 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);7370 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type,
7371 coro_promise_ptr, false);
7367 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);7372 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
7368 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7373 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7369 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);7374 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
...@@ -7387,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7387,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7387 ir_build_return(irb, coro_scope, node, undef);7392 ir_build_return(irb, coro_scope, node, undef);
73887393
7389 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);7394 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
7390 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);7395 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr,
7396 false);
7391 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);7397 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
73927398
7393 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);7399 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
...@@ -7465,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7465,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7465 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7471 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7466 false, false, PtrLenUnknown, 0, 0, 0));7472 false, false, PtrLenUnknown, 0, 0, 0));
7467 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);7473 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7468 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);7474 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7469 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,7475 result_ptr, false);
7470 irb->exec->coro_result_field_ptr);7476 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node,
7477 u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr, false);
7471 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,7478 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
7472 fn_entry->type_entry->data.fn.fn_type_id.return_type);7479 fn_entry->type_entry->data.fn.fn_type_id.return_type);
7473 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);7480 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
...@@ -7517,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7517,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7517 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7524 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7518 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7525 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7519 false, false, PtrLenUnknown, 0, 0, 0));7526 false, false, PtrLenUnknown, 0, 0, 0));
7520 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);7527 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7528 coro_mem_ptr_maybe, false);
7521 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);7529 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
7522 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);7530 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
7523 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);7531 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
...@@ -8644,15 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp...@@ -8644,15 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
8644 return err_set_type;8652 return err_set_type;
8645}8653}
86468654
8647static bool ptr_allows_addr_zero(ZigType *ptr_type) {
8648 if (ptr_type->id == ZigTypeIdPointer) {
8649 return ptr_type->data.pointer.allow_zero;
8650 } else if (ptr_type->id == ZigTypeIdOptional) {
8651 return true;
8652 }
8653 return false;
8654}
8655
8656static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,8655static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
8657 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)8656 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
8658{8657{
...@@ -11310,7 +11309,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11310,7 +11309,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11310 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&11309 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
11311 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))11310 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
11312 {11311 {
11313 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);11312 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
11314 }11313 }
11315 }11314 }
1131611315
...@@ -11352,7 +11351,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11352,7 +11351,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11352 actual_type->data.pointer.child_type, source_node,11351 actual_type->data.pointer.child_type, source_node,
11353 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)11352 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
11354 {11353 {
11355 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);11354 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
11356 }11355 }
1135711356
11358 // cast from integer to C pointer11357 // cast from integer to C pointer
...@@ -20616,7 +20615,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -20616,7 +20615,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
20616}20615}
2061720616
20618static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,20617static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
20619 ZigType *dest_type, IrInstruction *dest_type_src)20618 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on)
20620{20619{
20621 Error err;20620 Error err;
2062220621
...@@ -20685,7 +20684,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20685,7 +20684,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20685 return ira->codegen->invalid_instruction;20684 return ira->codegen->invalid_instruction;
20686 }20685 }
2068720686
20688 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr);20687 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
2068920688
20690 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {20689 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
20691 ErrorMsg *msg = ir_add_error(ira, source_instr,20690 ErrorMsg *msg = ir_add_error(ira, source_instr,
...@@ -20722,7 +20721,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct...@@ -20722,7 +20721,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
20722 if (type_is_invalid(src_type))20721 if (type_is_invalid(src_type))
20723 return ira->codegen->invalid_instruction;20722 return ira->codegen->invalid_instruction;
2072420723
20725 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);20724 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value,
20725 instruction->safety_check_on);
20726}20726}
2072720727
20728static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {20728static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {
test/runtime_safety.zig+10
...@@ -1,6 +1,16 @@...@@ -1,6 +1,16 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompareOutputContext) void {3pub fn addCases(cases: *tests.CompareOutputContext) void {
4 cases.addRuntimeSafety("pointer casting null to non-optional pointer",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);
7 \\}
8 \\pub fn main() void {
9 \\ var c_ptr: [*c]u8 = 0;
10 \\ var zig_ptr: *u8 = c_ptr;
11 \\}
12 );
13
4 cases.addRuntimeSafety("@intToEnum - no matching tag value",14 cases.addRuntimeSafety("@intToEnum - no matching tag value",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {15 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);16 \\ @import("std").os.exit(126);