diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-02-14 01:09:33 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-02-14 01:09:33 -0500 |
| commit | 59de24817e8538434f35a20a401f40c2f0231a9a (patch) | |
| tree | 7c06cd2749d2bb449742fc98dac59ab82a480b48 /src/codegen.cpp | |
| parent | d4d2718bca9e23ceec029bb505c0ea1b91c875b6 (diff) | |
| download | zig-59de24817e8538434f35a20a401f40c2f0231a9a.tar.gz zig-59de24817e8538434f35a20a401f40c2f0231a9a.zip | |
runtime safety check for casting null to pointer
see #1059
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 142e8174f5..dbb13ca885 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -950,6 +950,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { return buf_create_from_str("invalid enum value"); case PanicMsgIdFloatToInt: return buf_create_from_str("integer part of floating point value out of bounds"); + case PanicMsgIdPtrCastNull: + return buf_create_from_str("cast causes pointer to be null"); } zig_unreachable(); } @@ -3028,7 +3030,22 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, return nullptr; } LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); - return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); + LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); + bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); + if (!want_safety_check || ptr_allows_addr_zero(wanted_type)) + return result_ptr; + + LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr)); + LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, ""); + LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail"); + LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk"); + LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); + + LLVMPositionBuilderAtEnd(g->builder, fail_block); + gen_safety_crash(g, PanicMsgIdPtrCastNull); + + LLVMPositionBuilderAtEnd(g->builder, ok_block); + return result_ptr; } static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable, |
