Commit 42d9017feb

Bogdan Romanyuk <65823030+wrongnull@users.noreply.github.com>
2024-07-22 01:56:04
Sema: fix OOB access in coerceTupleToStruct (#19620)
Co-authored-by: Veikka Tuominen <git@vexu.eu>
1 parent 08cddaf
Changed files (2)
src
test
src/Sema.zig
@@ -31867,14 +31867,9 @@ fn coerceTupleToStruct(
     };
     for (0..field_count) |tuple_field_index| {
         const field_src = inst_src; // TODO better source location
-        const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {
-            .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
-                anon_struct_type.names.get(ip)[tuple_field_index]
-            else
-                try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{tuple_field_index}, .no_embedded_nulls),
-            .struct_type => ip.loadStructType(inst_ty.toIntern()).field_names.get(ip)[tuple_field_index],
-            else => unreachable,
-        };
+        const field_name = inst_ty.structFieldName(tuple_field_index, mod).unwrap() orelse
+            try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{tuple_field_index}, .no_embedded_nulls);
+
         const struct_field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
         const struct_field_ty = Type.fromInterned(struct_type.field_types.get(ip)[struct_field_index]);
         const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, @intCast(tuple_field_index));
@@ -31980,21 +31975,8 @@ fn coerceTupleToTuple(
     for (0..dest_field_count) |field_index_usize| {
         const field_i: u32 = @intCast(field_index_usize);
         const field_src = inst_src; // TODO better source location
-        const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {
-            .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
-                anon_struct_type.names.get(ip)[field_i]
-            else
-                try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_i}, .no_embedded_nulls),
-            .struct_type => s: {
-                const struct_type = ip.loadStructType(inst_ty.toIntern());
-                if (struct_type.field_names.len > 0) {
-                    break :s struct_type.field_names.get(ip)[field_i];
-                } else {
-                    break :s try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_i}, .no_embedded_nulls);
-                }
-            },
-            else => unreachable,
-        };
+        const field_name = inst_ty.structFieldName(field_index_usize, mod).unwrap() orelse
+            try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_index_usize}, .no_embedded_nulls);
 
         if (field_name.eqlSlice("len", ip))
             return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});
test/cases/compile_errors/invalid_tuple_to_struct_coercion.zig
@@ -0,0 +1,13 @@
+const S = struct {
+    fizz: void,
+};
+
+export fn entry() void {
+    _ = @as(S, struct { void }{{}});
+}
+
+// error
+// target=native
+//
+// :6:31: error: no field named '0' in struct 'tmp.S'
+// :1:11: note: struct declared here