aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-09-08 16:43:54 +0300
committerGitHub <noreply@github.com>2022-09-08 16:43:54 +0300
commit6a62a15ecde10300f6281e2d49fed34031d5f68a (patch)
treed0c5e7abd7ef2a1bc2b1d4ee283354f1da25322b /src
parenta7661f115dccf26b141557c923171f325cdc2757 (diff)
parentc7e45aebafef0372fe231816eeffd18198240f14 (diff)
downloadzig-6a62a15ecde10300f6281e2d49fed34031d5f68a.tar.gz
zig-6a62a15ecde10300f6281e2d49fed34031d5f68a.zip
Merge pull request #12773 from Vexu/stage2-fixes
Sema: fix UAF in zirClosureGet
Diffstat (limited to 'src')
-rw-r--r--src/Module.zig10
-rw-r--r--src/Sema.zig62
-rw-r--r--src/codegen/llvm.zig11
-rw-r--r--src/translate_c.zig2
4 files changed, 53 insertions, 32 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 3ae6c48edd..ea89225537 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -345,6 +345,15 @@ pub const CaptureScope = struct {
/// During sema, this map is backed by the gpa. Once sema completes,
/// it is reallocated using the value_arena.
captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, TypedValue) = .{},
+
+ pub fn failed(noalias self: *const @This()) bool {
+ return self.captures.available == 0 and self.captures.size == std.math.maxInt(u32);
+ }
+
+ pub fn fail(noalias self: *@This()) void {
+ self.captures.available = 0;
+ self.captures.size = std.math.maxInt(u32);
+ }
};
pub const WipCaptureScope = struct {
@@ -383,6 +392,7 @@ pub const WipCaptureScope = struct {
pub fn deinit(noalias self: *@This()) void {
if (!self.finalized) {
self.scope.captures.deinit(self.gpa);
+ self.scope.fail();
}
self.* = undefined;
}
diff --git a/src/Sema.zig b/src/Sema.zig
index fb1638bc2a..15e891ef87 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -5956,7 +5956,6 @@ fn analyzeCall(
error.NeededSourceLocation => {
_ = sema.inst_map.remove(inst);
const decl = sema.mod.declPtr(block.src_decl);
- child_block.src_decl = block.src_decl;
try sema.analyzeInlineCallArg(
block,
&child_block,
@@ -13740,6 +13739,16 @@ fn zirClosureGet(
const tv = while (true) {
// Note: We don't need to add a dependency here, because
// decls always depend on their lexical parents.
+
+ // Fail this decl if a scope it depended on failed.
+ if (scope.failed()) {
+ if (sema.owner_func) |owner_func| {
+ owner_func.state = .dependency_failure;
+ } else {
+ sema.owner_decl.analysis = .dependency_failure;
+ }
+ return error.AnalysisFail;
+ }
if (scope.captures.getPtr(inst_data.inst)) |tv| {
break tv;
}
@@ -18076,8 +18085,8 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
const target = sema.mod.getTarget();
try sema.resolveTypeLayout(block, lhs_src, ty);
- switch (ty.tag()) {
- .@"struct", .tuple, .anon_struct => {},
+ switch (ty.zigTypeTag()) {
+ .Struct => {},
else => {
const msg = msg: {
const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)});
@@ -19617,28 +19626,19 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
- const dest_ptr = try sema.resolveInst(extra.dest);
- const dest_ptr_ty = sema.typeOf(dest_ptr);
+ const uncasted_dest_ptr = try sema.resolveInst(extra.dest);
- try sema.checkPtrOperand(block, dest_src, dest_ptr_ty);
- if (dest_ptr_ty.isConstPtr()) {
- return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)});
- }
+ // TODO AstGen's coerced_ty cannot handle volatile here
+ var dest_ptr_info = Type.initTag(.manyptr_u8).ptrInfo().data;
+ dest_ptr_info.@"volatile" = sema.typeOf(uncasted_dest_ptr).isVolatilePtr();
+ const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, dest_ptr_info);
+ const dest_ptr = try sema.coerce(block, dest_ptr_ty, uncasted_dest_ptr, dest_src);
const uncasted_src_ptr = try sema.resolveInst(extra.source);
- const uncasted_src_ptr_ty = sema.typeOf(uncasted_src_ptr);
- try sema.checkPtrOperand(block, src_src, uncasted_src_ptr_ty);
- const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data;
- const wanted_src_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
- .pointee_type = dest_ptr_ty.elemType2(),
- .@"align" = src_ptr_info.@"align",
- .@"addrspace" = src_ptr_info.@"addrspace",
- .mutable = false,
- .@"allowzero" = src_ptr_info.@"allowzero",
- .@"volatile" = src_ptr_info.@"volatile",
- .size = .Many,
- });
- const src_ptr = try sema.coerce(block, wanted_src_ptr_ty, uncasted_src_ptr, src_src);
+ var src_ptr_info = Type.initTag(.manyptr_const_u8).ptrInfo().data;
+ src_ptr_info.@"volatile" = sema.typeOf(uncasted_src_ptr).isVolatilePtr();
+ const src_ptr_ty = try Type.ptr(sema.arena, sema.mod, src_ptr_info);
+ const src_ptr = try sema.coerce(block, src_ptr_ty, uncasted_src_ptr, src_src);
const len = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.byte_count), len_src);
const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
@@ -19674,14 +19674,15 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const value_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
- const dest_ptr = try sema.resolveInst(extra.dest);
- const dest_ptr_ty = sema.typeOf(dest_ptr);
- try sema.checkPtrOperand(block, dest_src, dest_ptr_ty);
- if (dest_ptr_ty.isConstPtr()) {
- return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)});
- }
- const elem_ty = dest_ptr_ty.elemType2();
- const value = try sema.coerce(block, elem_ty, try sema.resolveInst(extra.byte), value_src);
+ const uncasted_dest_ptr = try sema.resolveInst(extra.dest);
+
+ // TODO AstGen's coerced_ty cannot handle volatile here
+ var ptr_info = Type.initTag(.manyptr_u8).ptrInfo().data;
+ ptr_info.@"volatile" = sema.typeOf(uncasted_dest_ptr).isVolatilePtr();
+ const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
+ const dest_ptr = try sema.coerce(block, dest_ptr_ty, uncasted_dest_ptr, dest_src);
+
+ const value = try sema.coerce(block, Type.u8, try sema.resolveInst(extra.byte), value_src);
const len = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.byte_count), len_src);
const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: {
@@ -26013,6 +26014,7 @@ fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref
.pointee_type = decl_tv.ty,
.mutable = false,
.@"addrspace" = decl.@"addrspace",
+ .@"align" = decl.@"align",
}),
try Value.Tag.decl_ref.create(sema.arena, decl_index),
);
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 80ffd7a665..043f0bbdc7 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -9204,6 +9204,12 @@ pub const FuncGen = struct {
return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
}
+ if (info.pointee_type.isPtrAtRuntime()) {
+ const same_size_int = self.context.intType(elem_bits);
+ const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
+ return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
+ }
+
return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");
}
@@ -9235,7 +9241,10 @@ pub const FuncGen = struct {
// Convert to equally-sized integer type in order to perform the bit
// operations on the value to store
const value_bits_type = self.context.intType(elem_bits);
- const value_bits = self.builder.buildBitCast(elem, value_bits_type, "");
+ const value_bits = if (elem_ty.isPtrAtRuntime())
+ self.builder.buildPtrToInt(elem, value_bits_type, "")
+ else
+ self.builder.buildBitCast(elem, value_bits_type, "");
var mask_val = value_bits_type.constAllOnes();
mask_val = mask_val.constZExt(containing_int_ty);
diff --git a/src/translate_c.zig b/src/translate_c.zig
index e62f5b4568..014f6b1934 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -1167,7 +1167,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD
}
if (!c.zig_is_stage1 and is_packed) {
- return failDecl(c, record_loc, bare_name, "cannot translate packed record union", .{});
+ return failDecl(c, record_loc, name, "cannot translate packed record union", .{});
}
const record_payload = try c.arena.create(ast.Payload.Record);