Skip to content

Should windows_registry::Key::(get|set)_string use OsStr instead of str? #3119

Closed
@rami3l

Description

@rami3l

Hi, and thanks for making this project!

Background

Coming from rust-lang/rustup#3896, we (the Rustup team) are currently evaluating the possibility of replacing winreg with windows-registry in Rustup. This is mainly because we use the registry APIs to inspect and change the PATH variable, which is a necessary step in Rustup's installation process.

However, the following function signatures look a bit concerning:

pub fn get_string<T: AsRef<str>>(&self, name: T) -> Result<String> {

pub fn set_string<T: AsRef<str>>(&self, name: T, value: T) -> Result<()> {

... which is because being valid UTF8 is a core invariant of the str type. OTOH, it seems to me that there's no guarantee that we should always get/set valid UTF16LE from/to the registry, and we'd like to make sure that Rustup is still working correctly even if there are non-Unicode bytes in the registry value in question (which could be added by a third-party app?).

For example, we now have the following smoke test that inserts into the registry a sequence of u16 that would be considered malformed UTF16LE, and it's expected to work:

                // Set up a non unicode PATH
                let reg_value = RegValue {
                    bytes: vec![
                        0x00, 0xD8, // leading surrogate
                        0x01, 0x01, // bogus trailing surrogate
                        0x00, 0x00, // null
                    ],
                    vtype: RegType::REG_EXPAND_SZ,
                };
                RegKey::predef(HKEY_CURRENT_USER)
                    .open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
                    .unwrap()
                    .set_raw_value("PATH", &reg_value)
                    .unwrap();

https://github.com/rust-lang/rustup/blob/4c3ff9ce638e8402fbc2e8755d9e8a2cd148f6be/tests/suite/cli_paths.rs#L427-L440

Suggestion

For the exact reason explained above, I believe OsStr/OsString is a better alternative to str/String in APIs like this.

Quoting https://doc.rust-lang.org/std/ffi/struct.OsString.html:

The need for this type arises from the fact that:

  • On Windows, strings are often arbitrary sequences of non-zero 16-bit values, interpreted as UTF-16 when it is valid to do so.

Once that change is made, we would be able to use windows::ffi::OsStringExt::from_wide to construct an OsString from any &[u16].

I'm still not very familiar with Windows development myself, so please feel free to correct me if I'm wrong about anything.
Many thanks in advance!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions