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

zig build with safety on get "Illegal instruction" when using c "container_of" #15962

Closed
sogwms opened this issue Jun 6, 2023 · 4 comments
Closed

Comments

@sogwms
Copy link

sogwms commented Jun 6, 2023

Zig Version

0.10.1

Steps to Reproduce and Observed Behavior

m.c file

#define rt_container_of(ptr, type, member)  ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

struct rt_object
{
    char       name[8];                       /**< name of kernel object */
    char type;                                    /**< type of kernel object */
    char flag;                                    /**< flag of kernel object */

    unsigned int  list;                       /**< list node of kernel object */
};

static struct rt_object ko;

unsigned int getRootAddr() {
    char *cp = &ko.flag;

    return (unsigned int)(rt_container_of(cp, struct rt_object, flag));
}

m.h

unsigned int getRootAddr();

main.zig

const std = @import("std");

const rt = @cImport({
    @cInclude("m.h");
});

pub fn main() !void {
    // Prints to stderr (it's a shortcut based on `std.io.getStdErr()`)
    std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
    var rtt = rt.getRootAddr();

    // stdout is for the actual output of your application, for example if you
    // are implementing gzip, then only the compressed bytes should be sent to
    // stdout, not any debugging messages.
    const stdout_file = std.io.getStdOut().writer();
    var bw = std.io.bufferedWriter(stdout_file);
    const stdout = bw.writer();

    try stdout.print("var {?}.\n", .{rtt});

    try bw.flush(); // don't forget to flush!
}

build.zig

...
exe.addIncludePath("src");
exe.addCSourceFile("src/m.c", &[_][]const u8{"-std=c11"});
...

when run "zig build" and then run the generated .exe:
image

but if build without safety check, it's ok:

image

Expected Behavior

zig build with safety on should work well

@sogwms sogwms added the bug Observed behavior contradicts documented or intended behavior label Jun 6, 2023
@ehaas
Copy link
Sponsor Contributor

ehaas commented Jun 6, 2023

The rt_container_of macro contains a NULL pointer dereference (((struct rt_object *)0)->flag when macro expanded), which is undefined behavior. You can use offsetof for a portable way to do what that portion of the macro is trying to do.

@sogwms
Copy link
Author

sogwms commented Jun 6, 2023

Thanks for the solutions. Actually I am working on an embedded project mixing zig and c, the "rt_container_of" is almost everywhere in the c source code. It's really hard to locate the cause of "Illegal instruction" considering it's a runtime error and just results in “hard-fault” on baremetal not even a panic which can print useful debug message.

Hopefully the "Illegal instruction" can be a panic in the future.

@ifreund
Copy link
Member

ifreund commented Jun 6, 2023

Thanks for the solutions. Actually I am working on an embedded project mixing zig and c, the "rt_container_of" is almost everywhere in the c source code. It's really hard to locate the cause of "Illegal instruction" considering it's a runtime error and just results in “hard-fault” on baremetal not even a panic which can print useful debug message.

Hopefully the "Illegal instruction" can be a panic in the future.

That improvement is tracked by #5163

@ifreund ifreund closed this as completed Jun 6, 2023
@ifreund ifreund removed the bug Observed behavior contradicts documented or intended behavior label Jun 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants