-
Notifications
You must be signed in to change notification settings - Fork 385
make GetUserProfileDirectoryW more strictly match documented behavior #4332
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
Conversation
An undocumented behaviour of the function is that it will indeed set the size on success. The standard library has been relying on this for >10 years at this point https://github.com/rust-lang/rust/blob/70ed3a48dfa301c5bb56de3e0a7c25214539b83c/src/libstd/sys/windows/os.rs#L368. Maybe we shouldn't and instead the string should just be treated as null-terminated (which is guaranteed). Or maybe the Microsoft docs should just be updated to note the behaviour. |
Is that realistically achievable? Cc @cgettys-microsoft @sivadeilra |
Yes. Most of the Windows SDK is managed in a Git repo and Microsoft does accept (after review) edits to them. There is an "Edit this doc" link on the page for that API and it points to this URL: |
Wow, nice. :) I know way too little about Windows to attempt that, so I'll close this PR for now -- rust-lang/rust#141244 at least adds docs to std for this so it's more clear what the Miri comment refers to. @ChrisDenton do you think it is worth opening a rustc issue about this? |
For sure. We should be using the API as documented and it'd be good to track that how ever we end up fixing it. |
Done: rust-lang/rust#141254 |
… r=ChrisDenton windows: document that we rely on an undocumented property of GetUserProfileDirectoryW r? `@ChrisDenton` Also see rust-lang/miri#4332
Rollup merge of rust-lang#141244 - RalfJung:GetUserProfileDirectoryW, r=ChrisDenton windows: document that we rely on an undocumented property of GetUserProfileDirectoryW r? `@ChrisDenton` Also see rust-lang/miri#4332
@RalfJung A PR for this was already opened in 2024: MicrosoftDocs/sdk-api#1810 |
I'm of the (personal) opinion that Rust is already within the documented contract laid out by the static analysis annotations on the function signature; they say unambigiously that the size parameter is written on success since it's Inout - see MicrosoftDocs/sdk-api#1810 (comment) The documentation talks about the failure case because that's not expressed in the SAL annotations. |
It might be a tiny bit fuzzy - technically the |
Or in other words:
|
I'm going to read the SAL annotations again tomorrow when I'm better rested... and maybe @sivadeilra can take a look too. |
These SAL annotations do not show up in the docs, right? How would I even query them without having access to the SDK? And is there some statement that makes them normative on their own even if they say more than the docs say? |
Here's the header in question over there: https://github.com/microsoft/win32metadata/blob/c7ffce1c97bb724580580f3856b94c6d4ad677ed/generation/WinSDK/RecompiledIdlHeaders/um/UserEnv.h#L375 The SDK itself is also freely available, but not necessarily super accessible if you don't have a Windows machine, since it comes as an installer and a bunch of compressed files: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
Natively, C and C++ provide only limited ways for developers to consistently express intent and invariance. By using SAL annotations, you can describe your functions in greater detail so that developers who are consuming them can better understand how to use them." Of course, they're an imperfect tool, and they're not always used to their fullest extent, as they're a pretty complicated thing to understand. E.g. I'm pretty sure the question we're going back and forth on boils down to "should lpProfileDir be annotated with the more precise To which I personally believe the answer is "yes, as that's the current behavior and as far as I know, has been for a long time, and there's no other conceivable behavior that makes sense given that lpcchSize is annotated |
The type is an |
These older APIs can be challenging as you have to sometimes rely on some combination of the signature, SAL annotations, documentation, and observed behavior. Backward compatibility is also taken very seriously. In this case, the implementation specifically notes that the length is returned upon success for backward compatibility. |
Ah, right. I'm used to working in a code base that doesn't always use LPWSTR and usually uses the z suffix instead |
Closing the loop here for completeness - Arlie Davis (@sivadeilra) and Kenny Kerr (@kennykerr) reviewed that the implementation does in fact make this guarantee, and Drew Batchelor (@drewbatgit) kindly reviewed and merged the documentation update (MicrosoftDocs/sdk-api#1810). It'll probably take a bit to show up in the public doc pages - but it's been merged, so it will happen :). Thanks @ChrisDenton for the contribution! |
I already have a PR up based on that. :) |
I saw a second after I replied here :D |
I don't see an indication in the docs that
size
would be written to on success.However, std seems to rely on that. We get UB otherwise:
@ChrisDenton any idea why?
The logic for this is here.