Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coercing typed tuple to struct causes index OOB in Sema #19529

Closed
InKryption opened this issue Apr 4, 2024 · 1 comment · Fixed by #19620
Closed

Coercing typed tuple to struct causes index OOB in Sema #19529

InKryption opened this issue Apr 4, 2024 · 1 comment · Fixed by #19620
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Milestone

Comments

@InKryption
Copy link
Contributor

InKryption commented Apr 4, 2024

Zig Version

0.12.0-dev.3518+d2be725e4

Steps to Reproduce and Observed Behavior

Minimum reproduction:

comptime {
    _ = @as(struct { fizz: void }, struct { void }{{}});
}

Notes:

  • Error message in release fast is just "no field named 'd' in struct <destination struct type>".
  • The number or types of fields doesn't matter, any typed tuple literal (Tupletype{...}) coerced to any record struct type (even empty) produces the same misbehavior.
  • The out of bounds access occurs at src/Sema.zig:32265:86.

Expected Behavior

A proper compile error about not being able to coerce a tuple to a struct.

@InKryption InKryption added the bug Observed behavior contradicts documented or intended behavior label Apr 4, 2024
@InKryption
Copy link
Contributor Author

Stack trace with zig test repro.zig using debug build:

thread 77010 panic: index out of bounds: index 0, len 0
Analyzing repro.zig: repro.zig:comptime_0
      %2 = extended(struct_decl(hash(3e2d6bfb240330d048bafab267843b98) anon, {}, auto, {}, {
        fizz: @void_type,
      }) node_offset:3:13 to :3:34
      %3 = extended(struct_decl(hash(340b6ff9897bf15e42239147ac815784) tuple, anon, {}, auto, {}, {
        @"0": @void_type,
      }) node_offset:3:36 to :3:51
      %4 = validate_array_init_ty(%3, 1) node_offset:3:36 to :3:55
      %5 = array_init_elem_type(%3, 0)
      %6 = array_init(%3{@void_value}) node_offset:3:36 to :3:55
    > %7 = as_node(%2, %6) node_offset:3:36 to :3:55
      %8 = ensure_result_non_error(%7) node_offset:3:9 to :3:56
      %9 = break_inline(%1, @void_value)
    For full context, use the command
      zig ast-check -t repro.zig


/home/inkryption/ziglang/zig/src/Sema.zig:32265:86: 0x65ce475 in coerceTupleToStruct (zig)
            .struct_type => ip.loadStructType(inst_ty.toIntern()).field_names.get(ip)[field_i],
                                                                                     ^
/home/inkryption/ziglang/zig/src/Sema.zig:29453:48: 0x61fab21 in coerceExtra (zig)
                return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {
                                               ^
/home/inkryption/ziglang/zig/src/Sema.zig:10140:28: 0x6e4f840 in analyzeAs (zig)
    return sema.coerceExtra(block, dest_ty, operand, src, .{ .is_ret = is_ret, .no_cast_to_comptime_int = no_cast_to_comptime_int }) catch |err| switch (err) {
                           ^
/home/inkryption/ziglang/zig/src/Sema.zig:10097:26: 0x69a867c in zirAsNode (zig)
    return sema.analyzeAs(block, src, extra.dest_type, extra.operand, false);
                         ^
/home/inkryption/ziglang/zig/src/Sema.zig:1004:64: 0x64bcfe2 in analyzeBodyInner (zig)
            .as_node                      => try sema.zirAsNode(block, inst),
                                                               ^
/home/inkryption/ziglang/zig/src/Sema.zig:911:30: 0x61f0137 in analyzeInlineBody (zig)
    if (sema.analyzeBodyInner(block, body)) |_| {
                             ^
/home/inkryption/ziglang/zig/src/Sema.zig:937:39: 0x5f3f8fe in resolveInlineBody (zig)
    return (try sema.analyzeInlineBody(block, body, break_target)) orelse .unreachable_value;
                                      ^
/home/inkryption/ziglang/zig/src/Module.zig:3638:50: 0x5f3cba6 in semaDecl (zig)
    const result_ref = try sema.resolveInlineBody(&block_scope, decl_bodies.value_body, decl_inst);
                                                 ^
/home/inkryption/ziglang/zig/src/Module.zig:3016:32: 0x5d1bf21 in ensureDeclAnalyzed (zig)
        break :blk mod.semaDecl(decl_index) catch |err| switch (err) {
                               ^
/home/inkryption/ziglang/zig/src/Compilation.zig:3485:38: 0x5f17398 in processOneJob (zig)
            module.ensureDeclAnalyzed(decl_index) catch |err| switch (err) {
                                     ^
/home/inkryption/ziglang/zig/src/Compilation.zig:3359:30: 0x5d47eda in performAllTheWork (zig)
            try processOneJob(comp, work_item, main_progress_node);
                             ^
/home/inkryption/ziglang/zig/src/Compilation.zig:2132:31: 0x5d43412 in update (zig)
    try comp.performAllTheWork(main_progress_node);
                              ^
/home/inkryption/ziglang/zig/src/main.zig:4503:24: 0x5d74b4f in updateModule (zig)
        try comp.update(main_progress_node);
                       ^
/home/inkryption/ziglang/zig/src/main.zig:3414:17: 0x5ddd579 in buildOutputType (zig)
    updateModule(comp, color) catch |err| switch (err) {
                ^
/home/inkryption/ziglang/zig/src/main.zig:266:31: 0x5c25b1b in mainArgs (zig)
        return buildOutputType(gpa, arena, args, .zig_test);
                              ^
/home/inkryption/ziglang/zig/src/main.zig:206:20: 0x5c22885 in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/home/inkryption/ziglang/zig/zig-out/lib/zig/std/start.zig:511:37: 0x5c2231e in main (zig)
            const result = root.main() catch |err| {
                                    ^
???:?:?: 0x77f44bb0cccf in ??? (libc.so.6)
Unwind information for `libc.so.6:0x77f44bb0cccf` was not available, trace may be incomplete

And the error message using a ReleaseFast build of the compiler:

repro.zig:3:51: error: no field named 'd' in struct 'repro.comptime_0__struct_249'
    _ = @as(struct { fizz: void }, struct { void }{{}});
                                   ~~~~~~~~~~~~~~~^~~~
repro.zig:3:13: note: struct declared here
    _ = @as(struct { fizz: void }, struct { void }{{}});

@Vexu Vexu added the frontend Tokenization, parsing, AstGen, Sema, and Liveness. label Apr 4, 2024
@Vexu Vexu added this to the 0.13.0 milestone Apr 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants