| ... | @@ -6781,14 +6781,54 @@ fn intCast( | ... | @@ -6781,14 +6781,54 @@ fn intCast( |
| 6781 | return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{}); | 6781 | return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{}); |
| 6782 | } | 6782 | } |
| 6783 | | 6783 | |
| 6784 | // TODO insert safety check to make sure the value fits in the dest type | | |
| 6785 | _ = runtime_safety; | | |
| 6786 | | | |
| 6787 | if ((try sema.typeHasOnePossibleValue(block, dest_ty_src, dest_ty))) |opv| { | 6784 | if ((try sema.typeHasOnePossibleValue(block, dest_ty_src, dest_ty))) |opv| { |
| | 6785 | // requirement: intCast(u0, input) iff input == 0 |
| | 6786 | if (runtime_safety and block.wantSafety()) { |
| | 6787 | try sema.requireRuntimeBlock(block, operand_src); |
| | 6788 | const target = sema.mod.getTarget(); |
| | 6789 | const wanted_info = dest_ty.intInfo(target); |
| | 6790 | const wanted_bits = wanted_info.bits; |
| | 6791 | |
| | 6792 | if (wanted_bits == 0) { |
| | 6793 | const zero_inst = try sema.addConstant(sema.typeOf(operand), Value.zero); |
| | 6794 | const is_in_range = try block.addBinOp(.cmp_eq, operand, zero_inst); |
| | 6795 | try sema.addSafetyCheck(block, is_in_range, .cast_truncated_data); |
| | 6796 | } |
| | 6797 | } |
| | 6798 | |
| 6788 | return sema.addConstant(dest_ty, opv); | 6799 | return sema.addConstant(dest_ty, opv); |
| 6789 | } | 6800 | } |
| 6790 | | 6801 | |
| 6791 | try sema.requireRuntimeBlock(block, operand_src); | 6802 | try sema.requireRuntimeBlock(block, operand_src); |
| | 6803 | if (runtime_safety and block.wantSafety()) { |
| | 6804 | const target = sema.mod.getTarget(); |
| | 6805 | const operand_ty = sema.typeOf(operand); |
| | 6806 | const actual_info = operand_ty.intInfo(target); |
| | 6807 | const wanted_info = dest_ty.intInfo(target); |
| | 6808 | const actual_bits = actual_info.bits; |
| | 6809 | const wanted_bits = wanted_info.bits; |
| | 6810 | |
| | 6811 | // requirement: signed to unsigned >= 0 |
| | 6812 | if (actual_info.signedness == .signed and |
| | 6813 | wanted_info.signedness == .unsigned) |
| | 6814 | { |
| | 6815 | const zero_inst = try sema.addConstant(sema.typeOf(operand), Value.zero); |
| | 6816 | const is_in_range = try block.addBinOp(.cmp_gte, operand, zero_inst); |
| | 6817 | try sema.addSafetyCheck(block, is_in_range, .cast_truncated_data); |
| | 6818 | } |
| | 6819 | |
| | 6820 | // requirement: unsigned int value fits into target type |
| | 6821 | if (actual_bits > wanted_bits or |
| | 6822 | (actual_bits == wanted_bits and |
| | 6823 | actual_info.signedness == .unsigned and |
| | 6824 | wanted_info.signedness == .signed)) |
| | 6825 | { |
| | 6826 | const max_int = try dest_ty.maxInt(sema.arena, target); |
| | 6827 | const max_int_inst = try sema.addConstant(operand_ty, max_int); |
| | 6828 | const is_in_range = try block.addBinOp(.cmp_lte, operand, max_int_inst); |
| | 6829 | try sema.addSafetyCheck(block, is_in_range, .cast_truncated_data); |
| | 6830 | } |
| | 6831 | } |
| 6792 | return block.addTyOp(.intcast, dest_ty, operand); | 6832 | return block.addTyOp(.intcast, dest_ty, operand); |
| 6793 | } | 6833 | } |
| 6794 | | 6834 | |
| ... | @@ -16166,6 +16206,7 @@ pub const PanicId = enum { | ... | @@ -16166,6 +16206,7 @@ pub const PanicId = enum { |
| 16166 | incorrect_alignment, | 16206 | incorrect_alignment, |
| 16167 | invalid_error_code, | 16207 | invalid_error_code, |
| 16168 | index_out_of_bounds, | 16208 | index_out_of_bounds, |
| | 16209 | cast_truncated_data, |
| 16169 | }; | 16210 | }; |
| 16170 | | 16211 | |
| 16171 | fn addSafetyCheck( | 16212 | fn addSafetyCheck( |
| ... | @@ -16288,6 +16329,7 @@ fn safetyPanic( | ... | @@ -16288,6 +16329,7 @@ fn safetyPanic( |
| 16288 | .incorrect_alignment => "incorrect alignment", | 16329 | .incorrect_alignment => "incorrect alignment", |
| 16289 | .invalid_error_code => "invalid error code", | 16330 | .invalid_error_code => "invalid error code", |
| 16290 | .index_out_of_bounds => "attempt to index out of bounds", | 16331 | .index_out_of_bounds => "attempt to index out of bounds", |
| | 16332 | .cast_truncated_data => "integer cast truncated bits", |
| 16291 | }; | 16333 | }; |
| 16292 | | 16334 | |
| 16293 | const msg_inst = msg_inst: { | 16335 | const msg_inst = msg_inst: { |
| ... | @@ -19964,6 +20006,14 @@ fn analyzeSlice( | ... | @@ -19964,6 +20006,14 @@ fn analyzeSlice( |
| 19964 | slice_ty = ptr_ptr_child_ty; | 20006 | slice_ty = ptr_ptr_child_ty; |
| 19965 | array_ty = ptr_ptr_child_ty; | 20007 | array_ty = ptr_ptr_child_ty; |
| 19966 | elem_ty = ptr_ptr_child_ty.childType(); | 20008 | elem_ty = ptr_ptr_child_ty.childType(); |
| | 20009 | |
| | 20010 | if (ptr_ptr_child_ty.ptrSize() == .C) { |
| | 20011 | if (try sema.resolveDefinedValue(block, ptr_src, ptr_or_slice)) |ptr_val| { |
| | 20012 | if (ptr_val.isNull()) { |
| | 20013 | return sema.fail(block, ptr_src, "slice of null pointer", .{}); |
| | 20014 | } |
| | 20015 | } |
| | 20016 | } |
| 19967 | }, | 20017 | }, |
| 19968 | .Slice => { | 20018 | .Slice => { |
| 19969 | ptr_sentinel = ptr_ptr_child_ty.sentinel(); | 20019 | ptr_sentinel = ptr_ptr_child_ty.sentinel(); |
| ... | @@ -20162,6 +20212,12 @@ fn analyzeSlice( | ... | @@ -20162,6 +20212,12 @@ fn analyzeSlice( |
| 20162 | | 20212 | |
| 20163 | try sema.requireRuntimeBlock(block, src); | 20213 | try sema.requireRuntimeBlock(block, src); |
| 20164 | if (block.wantSafety()) { | 20214 | if (block.wantSafety()) { |
| | 20215 | // requirement: slicing C ptr is non-null |
| | 20216 | if (ptr_ptr_child_ty.isCPtr()) { |
| | 20217 | const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true); |
| | 20218 | try sema.addSafetyCheck(block, is_non_null, .unwrap_null); |
| | 20219 | } |
| | 20220 | |
| 20165 | // requirement: end <= len | 20221 | // requirement: end <= len |
| 20166 | const opt_len_inst = if (array_ty.zigTypeTag() == .Array) | 20222 | const opt_len_inst = if (array_ty.zigTypeTag() == .Array) |
| 20167 | try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel()) | 20223 | try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel()) |