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
Add HLOCAL and HGLOBAL typedefs #1296
Comments
Contrast that with the far more common (and efficient) |
Thank you for your insights, @kennykerr. Using |
I think it's important to better distinguish between pointers and pointer-sized integers. The pointer vs. integer distinction matters to languages such as Rust. And the metadata can't always guess if something is "really" a pointer or not. Take a struct like
So I think the best thing to do is to follow the C/C++ headers more accurately. |
Handles are not pointers so this looks correct though. |
That has a couple of problems:
|
A similar discussion on HANDLE provenance occurred here microsoft/windows-rs#1643 tl;dr: I'm not aware of any cases where a returned handle is designed to be used as a pointer by the developer. |
And also here and here (where I'm coming from).
But, whatever the reason for it, they are stored and passed as pointers in C++ code that uses the headers.
That's all very well and good but existing C++ libraries do and some parts of the docs even encourage it. |
My understanding is that the call for handle strict provenance research required folks to go back to the handle source and figure out what the value truly represents. Or in other words, tease apart the intent from the implementation. I did a bunch of that work, scouring through Windows 1.0 manuals and notes, code, etc. and couldn't find a case where a handle returned by Windows APIs was meant to be used as a true pointer to a chunk of memory. The manuals really did document this as an opaque integer. So I'm in mind, the provenance of handles, as an integer type, for the Win32 API surface has been effectively established/settled. That said, I recognize--and you point out--there are cases where Windows APIs have handle-typed inputs that can be used to smuggle pointers around. In those cases, I believe we have to determine whether or not the intent of that parameter is to pass pointers around. So looking at The sticking point appears to be that the docs also indicate that apps are free to use that member for whatever they want. Ugh. Metadata could just slap a pointer type on that field and call it day. But in a hypothetical system where pointer provenence is validated (e.g. CHERI), problems will arise in scenarios where the field is used correctly by devs to hold normal event handles! I'm not sure there's a clear path forward here. We could...
|
Or
|
There actually is one handle typedef in the metadata that is strictly 32-bit, IIRC. So we shouldn't change all of them, regardless. There's been a lot of talk about specific APIs in this discussion, and TBH I haven't studied it all. My main interest is that the metadata have a prescribed way by which an API can be distinguished between pointer sized ints and pointers, and that the bulk of the APIs be represented accurately. After that, specific APIs can be switched from one representation to another by individual issues and discussions. |
Is it MSIHANDLE? This one is a bit special in that Windows can expect an application to parse it from a string; see the CommandLine column of MsiEmbeddedChainer Table. HINSTANCE and HMODULE are documented to be base addresses; but LoadLibraryEx can also set some of the least significant bits to indicate how the library was loaded. |
Yes, that's the one. |
Edit: Just realized I just repeated what Kenny said above #1296 (comment). Ignore me. Are there any actionable tasks/issues in this thread? |
From my issue description:
I'd like to get a clear idea of what the metadata does or may be able to offer for these. Here's my draft:
|
That looks fair to me; so we need to change the |
|
|
I feel it's worth noting, for the various kinds of smuggling data:
|
Consider
LocalAlloc
, which takes two parameters (one being a pointer-sized integer) and returns a pointer. In the metadata, both pointer-sized values are represented merely asnative int
(well, one isnative uint
, but that's irrelevant). As a result, a projection cannot discern between what should be expressed as an integer vs. a pointer. In theLocalAlloc
case, the optimal declaration would beLocalFree
is another example, where both the parameter and the return type are actually supposed to be pointers.And the info we want is in the headers. For example in the headers,
SIZE_T
is often used for a pointer-sized integer, whereasHLOCAL
is used where we want a pointer.HLOCAL
is a typedef ofHGLOBAL
which is a typedef ofHANDLE
, which ... is undefined except that it's pointer-sized and should generally be considered an opaque value.So we need two things:
Consider maybe creating 3 classifications: pointers, pointer-sized integers, and pointer-sized opaque values. in C#, we have distinct types we can use for all 3 of these.
See also #983, which may be considered a very specific form of this problem.
The text was updated successfully, but these errors were encountered: