diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-02-14 00:40:39 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-02-14 00:40:39 -0500 |
| commit | d4d2718bca9e23ceec029bb505c0ea1b91c875b6 (patch) | |
| tree | c2b7b61f36fff694f5ff030fde50846b23c690cd | |
| parent | 5699ab5e77f8d13cac1e34775e6e51358119965c (diff) | |
| download | zig-d4d2718bca9e23ceec029bb505c0ea1b91c875b6.tar.gz zig-d4d2718bca9e23ceec029bb505c0ea1b91c875b6.zip | |
comptime detection of casting null to pointer
See #1059
| -rw-r--r-- | src/ir.cpp | 17 | ||||
| -rw-r--r-- | test/compile_errors.zig | 20 |
2 files changed, 34 insertions, 3 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 19bec193d5..f064adb128 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -20645,12 +20645,23 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ } if (instr_is_comptime(ptr)) { - // Undefined is OK here; @ptrCast is defined to reinterpret the bit pattern - // of the pointer as the new pointer type. - ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); + bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type); + UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad; + ConstExprValue *val = ir_resolve_const(ira, ptr, is_undef_allowed); if (!val) return ira->codegen->invalid_instruction; + if (val->special == ConstValSpecialStatic) { + bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull || + (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && + val->data.x_ptr.data.hard_coded_addr.addr == 0); + if (is_addr_zero && !dest_allows_addr_zero) { + ir_add_error(ira, source_instr, + buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name))); + return ira->codegen->invalid_instruction; + } + } + IrInstruction *result = ir_const(ira, source_instr, dest_type); copy_const_val(&result->value, val, false); result->value.type = dest_type; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index c51a65cadf..71ee4901ff 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,26 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompileErrorContext) void { cases.addTest( + "implicit casting null c pointer to zig pointer", + \\comptime { + \\ var c_ptr: [*c]u8 = 0; + \\ var zig_ptr: *u8 = c_ptr; + \\} + , + ".tmp_source.zig:3:24: error: null pointer casted to type '*u8'", + ); + + cases.addTest( + "implicit casting undefined c pointer to zig pointer", + \\comptime { + \\ var c_ptr: [*c]u8 = undefined; + \\ var zig_ptr: *u8 = c_ptr; + \\} + , + ".tmp_source.zig:3:24: error: use of undefined value here causes undefined behavior", + ); + + cases.addTest( "implicit casting C pointers which would mess up null semantics", \\export fn entry() void { \\ var slice: []const u8 = "aoeu"; |
