Commit 82c8e45a7e

mlugg <mlugg@mlugg.co.uk>
2023-08-21 02:35:35
Sema: check @memset operand provides length
Resolves: #16698
1 parent 60fc18b
Changed files (2)
src
test
cases
compile_errors
src/Sema.zig
@@ -23938,7 +23938,26 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
         return sema.fail(block, dest_src, "cannot memset constant pointer", .{});
     }
 
-    const dest_elem_ty = dest_ptr_ty.elemType2(mod);
+    const dest_elem_ty: Type = dest_elem_ty: {
+        const ptr_info = dest_ptr_ty.ptrInfo(mod);
+        switch (ptr_info.flags.size) {
+            .Slice => break :dest_elem_ty ptr_info.child.toType(),
+            .One => {
+                if (ptr_info.child.toType().zigTypeTag(mod) == .Array) {
+                    break :dest_elem_ty ptr_info.child.toType().childType(mod);
+                }
+            },
+            .Many, .C => {},
+        }
+        return sema.failWithOwnedErrorMsg(msg: {
+            const msg = try sema.errMsg(block, src, "unknown @memset length", .{});
+            errdefer msg.destroy(sema.gpa);
+            try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{
+                dest_ptr_ty.fmt(mod),
+            });
+            break :msg msg;
+        });
+    };
 
     const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: {
         const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, "len"), dest_src);
test/cases/compile_errors/memset_no_length.zig
@@ -0,0 +1,17 @@
+export fn foo() void {
+    var ptr: [*]u8 = undefined;
+    @memset(ptr, 123);
+}
+export fn bar() void {
+    var ptr: [*c]bool = undefined;
+    @memset(ptr, true);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :3:5: error: unknown @memset length
+// :3:13: note: destination type '[*]u8' provides no length
+// :7:5: error: unknown @memset length
+// :7:13: note: destination type '[*c]bool' provides no length