Skip to content

The Curious Case Of HANDLE and SOCKET #1643

Closed
@Gankra

Description

@Gankra

Here is a list of type definitions from many different sources:

wintnt.h:

typedef void *HANDLE;
...
typedef PVOID HANDLE;

WinSock.h / WinSock2.h

typedef UINT_PTR        SOCKET;

windows_sys::Win32::Foundation::HANDLE
windows_sys::Win32::Networking::WinSock::SOCKET

pub type HANDLE = isize;
pub type SOCKET = usize;

rust\library\std\src\sys\windows\c.rs:
rust\library\std\src\os\windows\c.rs:

pub type HANDLE = LPVOID;
pub type SOCKET = u64;

std::os::windows::raw::HANDLE:
std::os::windows::raw::SOCKET:

pub type HANDLE = *mut c_void;
pub type SOCKET = u64;

Windows Socket Handles Docs

(I'm assuming this is talking about SOCKET, Microsoft's docs really hate linking these types.)

A socket handle can optionally be a file handle in Windows Sockets 2. A socket handle from a Winsock provider can be used with other non-Winsock functions such as ReadFile, WriteFile, ReadFileEx, and WriteFileEx.


So as part of strict_provenance I have been trying to make code more consistent / honest about values which are "pointers" vs "integers". These APIs are the bane of my existence.

  • Everyone but windows_sys agrees a HANDLE is a pointer
  • Everyone agrees SOCKET is an integer
  • Micosoft's APIs then declare / require that it's ok to "pun" a SOCKET as a HANDLE

This made me very confused, and every time I checked a definition it was Slightly Different.

As far as I can tell both of these types are actually always integers (the kernel can't just hand userspace a pointer and then expect it to be a useful pointer if it's ever passed back to it, so it "must" be an integer and if you ask anyone with knowledge of the kernel they will say as much). Presumably HANDLE is just so ancient that Microsoft handn't figured out the Magic of UINT_PTR yet.

So windows_sys is, in some sense, the one being Honest here. If these types are in fact always integers this mess is actually fine because under strict provenance it's "always ok for an integer to pretend to be a pointer For Fun". It's just, very hard to tell that this is what's Happening based on the surface definitions and types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions