authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-22 16:23:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-22 16:23:34-07:00
logb24e9b6347afc66aa94f61b3ed4c2d02cdb0d0ee
tree7a9d2af51b046c8422facc14377b99a210250787
parentf0dcdd7931f1eb4f3b6a0a87c914baf770f6df03

Sema: fix a couple use-after-free bugs

Also switch to the more efficient encoding of the bitcast instruction when the destination type is anyerror in 2 common cases. LLVM backend: fix using the wrong type as the optional payload type in the `wrap_optional` AIR instruction.

2 files changed, 41 insertions(+), 23 deletions(-)

src/Sema.zig+39-19
......@@ -224,6 +224,16 @@ pub const Block = struct {
224224 });
225225 }
226226
227 pub fn addBitCast(block: *Block, ty: Type, operand: Air.Inst.Ref) Allocator.Error!Air.Inst.Ref {
228 return block.addInst(.{
229 .tag = .bitcast,
230 .data = .{ .ty_op = .{
231 .ty = try block.sema.addType(ty),
232 .operand = operand,
233 } },
234 });
235 }
236
227237 pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {
228238 return block.addInst(.{
229239 .tag = tag,
......@@ -1409,7 +1419,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
14091419 // for the inferred allocation.
14101420 // This instruction will not make it to codegen; it is only to participate
14111421 // in the `stored_inst_list` of the `inferred_alloc`.
1412 const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value);
1422 const operand = try block.addBitCast(pointee_ty, .void_value);
14131423 try inferred_alloc.stored_inst_list.append(sema.arena, operand);
14141424 },
14151425 .inferred_alloc_comptime => {
......@@ -1436,7 +1446,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
14361446 }
14371447 }
14381448 try sema.requireRuntimeBlock(block, src);
1439 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
1449 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
14401450 return bitcasted_ptr;
14411451}
14421452
......@@ -2509,7 +2519,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
25092519 // if expressions should force it when the condition is compile-time known.
25102520 const src: LazySrcLoc = .unneeded;
25112521 try sema.requireRuntimeBlock(block, src);
2512 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
2522 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
25132523 return sema.storePtr(block, src, bitcasted_ptr, value);
25142524}
25152525
......@@ -2555,7 +2565,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
25552565 .pointee_type = operand_ty,
25562566 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
25572567 });
2558 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
2568 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
25592569 return sema.storePtr(block, src, bitcasted_ptr, operand);
25602570 }
25612571 unreachable;
......@@ -4310,7 +4320,7 @@ fn zirErrorToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
43104320 }
43114321
43124322 try sema.requireRuntimeBlock(block, src);
4313 return block.addTyOp(.bitcast, result_ty, op_coerced);
4323 return block.addBitCast(result_ty, op_coerced);
43144324}
43154325
43164326fn zirIntToError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -4340,7 +4350,13 @@ fn zirIntToError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
43404350 // const is_gt_max = @panic("TODO get max errors in compilation");
43414351 // try sema.addSafetyCheck(block, is_gt_max, .invalid_error_code);
43424352 }
4343 return block.addTyOp(.bitcast, Type.anyerror, op);
4353 return block.addInst(.{
4354 .tag = .bitcast,
4355 .data = .{ .ty_op = .{
4356 .ty = Air.Inst.Ref.anyerror_type,
4357 .operand = op,
4358 } },
4359 });
43444360}
43454361
43464362fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -4483,7 +4499,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
44834499 }
44844500
44854501 try sema.requireRuntimeBlock(block, src);
4486 return block.addTyOp(.bitcast, int_tag_ty, enum_tag);
4502 return block.addBitCast(int_tag_ty, enum_tag);
44874503}
44884504
44894505fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -9620,7 +9636,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
96209636 try sema.addSafetyCheck(block, is_aligned, .incorrect_alignment);
96219637 }
96229638 }
9623 return block.addTyOp(.bitcast, type_res, operand_coerced);
9639 return block.addBitCast(type_res, operand_coerced);
96249640}
96259641
96269642fn zirErrSetCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -9650,7 +9666,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
96509666 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
96519667 return sema.addConstant(dest_ty, val);
96529668 }
9653 return block.addTyOp(.bitcast, dest_ty, operand);
9669 return block.addBitCast(dest_ty, operand);
96549670}
96559671
96569672fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -11871,7 +11887,7 @@ fn coerce(
1187111887 return sema.addConstant(dest_ty, val);
1187211888 }
1187311889 try sema.requireRuntimeBlock(block, inst_src);
11874 return block.addTyOp(.bitcast, dest_ty, inst);
11890 return block.addBitCast(dest_ty, inst);
1187511891 }
1187611892
1187711893 // undefined to anything
......@@ -11896,8 +11912,7 @@ fn coerce(
1189611912 }
1189711913
1189811914 // T to ?T
11899 var buf: Type.Payload.ElemType = undefined;
11900 const child_type = dest_ty.optionalChild(&buf);
11915 const child_type = try dest_ty.optionalChildAlloc(sema.arena);
1190111916 const intermediate = try sema.coerce(block, child_type, inst, inst_src);
1190211917 return sema.wrapOptional(block, dest_ty, intermediate, inst_src);
1190311918 },
......@@ -12603,11 +12618,10 @@ fn beginComptimePtrLoad(
1260312618 .opt_payload_ptr => {
1260412619 const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
1260512620 const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr);
12606 var buf: Type.Payload.ElemType = undefined;
1260712621 return ComptimePtrLoadKit{
1260812622 .root_val = parent.root_val,
1260912623 .val = parent.val.castTag(.opt_payload).?.data,
12610 .ty = parent.ty.optionalChild(&buf),
12624 .ty = try parent.ty.optionalChildAlloc(sema.arena),
1261112625 .byte_offset = undefined,
1261212626 .is_mutable = parent.is_mutable,
1261312627 };
......@@ -12643,7 +12657,7 @@ fn bitCast(
1264312657 return sema.addConstant(dest_ty, result_val);
1264412658 }
1264512659 try sema.requireRuntimeBlock(block, inst_src);
12646 return block.addTyOp(.bitcast, dest_ty, inst);
12660 return block.addBitCast(dest_ty, inst);
1264712661}
1264812662
1264912663fn coerceArrayPtrToSlice(
......@@ -12756,7 +12770,7 @@ fn coerceEnumToUnion(
1275612770
1275712771 // If the union has all fields 0 bits, the union value is just the enum value.
1275812772 if (union_ty.unionHasAllZeroBitFieldTypes()) {
12759 return block.addTyOp(.bitcast, union_ty, enum_tag);
12773 return block.addBitCast(union_ty, enum_tag);
1276012774 }
1276112775
1276212776 // TODO resolve the field names and add a hint that says "field 'foo' has type 'bar'"
......@@ -12814,7 +12828,7 @@ fn coerceVectorInMemory(
1281412828 }
1281512829
1281612830 try sema.requireRuntimeBlock(block, inst_src);
12817 return block.addTyOp(.bitcast, dest_ty, inst);
12831 return block.addBitCast(dest_ty, inst);
1281812832}
1281912833
1282012834fn coerceCompatibleErrorSets(
......@@ -12828,7 +12842,13 @@ fn coerceCompatibleErrorSets(
1282812842 return sema.addConstant(Type.anyerror, err_set_val);
1282912843 }
1283012844 try sema.requireRuntimeBlock(block, err_set_src);
12831 return block.addTyOp(.bitcast, Type.anyerror, err_set);
12845 return block.addInst(.{
12846 .tag = .bitcast,
12847 .data = .{ .ty_op = .{
12848 .ty = Air.Inst.Ref.anyerror_type,
12849 .operand = err_set,
12850 } },
12851 });
1283212852}
1283312853
1283412854fn analyzeDeclVal(
......@@ -13128,7 +13148,7 @@ fn analyzeSlice(
1312813148 if (opt_new_ptr_val) |new_ptr_val| {
1312913149 return sema.addConstant(return_ty, new_ptr_val);
1313013150 } else {
13131 return block.addTyOp(.bitcast, return_ty, new_ptr);
13151 return block.addBitCast(return_ty, new_ptr);
1313213152 }
1313313153 }
1313413154
src/codegen/llvm.zig+2-4
......@@ -2598,9 +2598,9 @@ pub const FuncGen = struct {
25982598 if (self.liveness.isUnused(inst)) return null;
25992599
26002600 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2601 const operand_ty = self.air.typeOf(ty_op.operand);
2601 const payload_ty = self.air.typeOf(ty_op.operand);
26022602 const non_null_bit = self.context.intType(1).constAllOnes();
2603 if (!operand_ty.hasCodeGenBits()) return non_null_bit;
2603 if (!payload_ty.hasCodeGenBits()) return non_null_bit;
26042604 const operand = try self.resolveInst(ty_op.operand);
26052605 const optional_ty = self.air.typeOfIndex(inst);
26062606 if (optional_ty.isPtrLikeOptional()) return operand;
......@@ -2608,8 +2608,6 @@ pub const FuncGen = struct {
26082608 if (isByRef(optional_ty)) {
26092609 const optional_ptr = self.buildAlloca(llvm_optional_ty);
26102610 const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, "");
2611 var buf: Type.Payload.ElemType = undefined;
2612 const payload_ty = operand_ty.optionalChild(&buf);
26132611 var ptr_ty_payload: Type.Payload.ElemType = .{
26142612 .base = .{ .tag = .single_mut_pointer },
26152613 .data = payload_ty,