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

Windows std.c incorrect function prototypes #10934

Open
Sirius902 opened this issue Feb 19, 2022 · 2 comments
Open

Windows std.c incorrect function prototypes #10934

Sirius902 opened this issue Feb 19, 2022 · 2 comments
Labels
bug Observed behavior contradicts documented or intended behavior contributor friendly This issue is limited in scope and/or knowledge of Zig internals. os-windows standard library This issue involves writing Zig code for the standard library.
Milestone

Comments

@Sirius902
Copy link

Sirius902 commented Feb 19, 2022

Zig Version

0.10.0-dev.856+e86a89d3f

Steps to Reproduce

When using std.c on Windows, there are functions externed using Unix prototypes such as recvfrom which causes unexpected behavior because the Windows function prototypes are different. Also, functions like getdirentries are present when compiling on Windows even though they are not present on Windows which causes an undefined reference when attempting to use them.

For example, the Unix prototype of recvfrom is the following:

ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
       int flags, struct sockaddr *restrict address,
       socklen_t *restrict address_len);

However, on Windows the prototype is this instead:

int recvfrom(
  [in]                SOCKET   s,
  [out]               char     *buf,
  [in]                int      len,
  [in]                int      flags,
  [out]               sockaddr *from,
  [in, out, optional] int      *fromlen
);

For reference, this is how it is declared in std.c.

pub extern "c" fn recvfrom(
    sockfd: c.fd_t,
    noalias buf: *anyopaque,
    len: usize,
    flags: u32,
    noalias src_addr: ?*c.sockaddr,
    noalias addrlen: ?*c.socklen_t,
) isize;

Because the return types are not the same and the functions are extern'd, the below behavior is observed.

Expected Behavior

const std = @import("std");

pub fn main() void {
    std.log.info("{}", .{std.c.getdirentries});
}

I would expect the above program to output the following error

.\src\main.zig:4:33: error: container 'std.c' has no member called 'getdirentries'
    std.log.info("{}", .{std.c.getdirentries});

And I would expect the below code to receive data from the socket and not return an error. As far as I know there shouldn't be anything wrong this example.
I would expect the following example to return an error from the function due to the length parameter being larger than the sockaddr.

const std = @import("std");
const os = std.os;

pub fn main() !void {
    const sock = try os.socket(os.AF.INET, os.SOCK.DGRAM, 0);
    defer os.closeSocket(sock);

    const address = std.net.Address.initIp4([_]u8{ 127, 0, 0, 1 }, 4096);
    try os.bind(sock, &address.any, address.getOsSockLen());

    var buffer: [std.mem.page_size]u8 = undefined;
    var sockaddr: os.sockaddr = undefined;
    var len: os.socklen_t = undefined;
    const read_len = try os.recvfrom(sock, &buffer, 0, &sockaddr, &len);
    std.log.info("read_len = {}", .{read_len});
}

Actual Behavior

The first example from above has the following compiler error

lld-link: error: undefined symbol: getdirentries

and the second example yields the following output

info: read_len = 4294967295

Due to the difference in the return types of recvfrom on Windows and Unix platforms, and due to #9971 meaning that std.os.recvfrom calls std.c.recvfrom, the return value of std.c.recvfrom is interpreted as an isize when it is actually a c_int and causes 4294967295 to be returned from the function instead of -1.

Also, calling std.os.windows.ws2_32.WSAGetLastError() afterwards indicates that the error that occurred was WSAEFAULT which indicates the following:
> Bad address.
The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).

I believe this means that there is also an issue with how the socket types are defined on Windows as well.

Edit: There actually is a bug in this example, len should be @sizeOf(@TypeOf(sockaddr)), but the above symptoms will show any time a function like std.c.recvfrom return -1 to indicate an error.

@Sirius902 Sirius902 added the bug Observed behavior contradicts documented or intended behavior label Feb 19, 2022
@ifreund ifreund added contributor friendly This issue is limited in scope and/or knowledge of Zig internals. standard library This issue involves writing Zig code for the standard library. labels Feb 20, 2022
@ifreund ifreund added this to the 0.10.0 milestone Feb 20, 2022
@radiohertz
Copy link

radiohertz commented Feb 20, 2022

Seems to me that many C library functions that are in unistd.h are directly defined in std/c.zig

Ex:
https://github.com/ziglang/zig/blob/master/lib/std/c.zig#L109-L152

@ifreund would adding a c/posix.zig and moving these definitions and importing them in systems that have unistd.h be a acceptable change? I can make a PR

@ifreund
Copy link
Member

ifreund commented Feb 20, 2022

@ifreund would adding a c/posix.zig and moving these definitions and importing them in systems that have unistd.h be a acceptable change? I can make a PR

Perhaps, see #6600 for context.

@andrewrk andrewrk modified the milestones: 0.10.0, 0.11.0 Apr 16, 2022
@andrewrk andrewrk modified the milestones: 0.11.0, 0.12.0 Jun 19, 2023
@andrewrk andrewrk modified the milestones: 0.14.0, 0.16.0 Aug 8, 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 contributor friendly This issue is limited in scope and/or knowledge of Zig internals. os-windows standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

No branches or pull requests

4 participants