◐ Shell
clean mode source ↗

bpo-39413: Implement os.unsetenv() on Windows by vstinner · Pull Request #18163 · python/cpython

Consider calling _wputenv_s, which has separate parameters for the name and value. Also, other win32_ functions in this module take C data types. I think it would be simpler to change the clinic definition of os.putenv and os.unsetenv to use Py_UNICODE. This is argument type "u", which is based on PyUnicode_AsUnicodeAndSize and checks for embedded null characters. The code for os_unsetenv_impl would change to calling win32_putenv(name, L""). Here's what this might look like -- off the top my head, so excuse any errors:

static PyObject *
win32_putenv(wchar_t *name, wchar_t *value)
{
    size_t name_length = wcslen(name);
    
    if (!name_length || wcschr(name, L'=')) {
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
        return NULL;
    }
    
    if (name_length >= _MAX_ENV) {
        PyErr_Format(PyExc_ValueError, "the environment variable name "
            "is longer than %u characters", _MAX_ENV - 1);
        return NULL;
    }
    
    if (wcslen(value) >= _MAX_ENV) {
        PyErr_Format(PyExc_ValueError, "the environment variable value "
            "is longer than %u characters", _MAX_ENV - 1);
        return NULL;
    }

    /* Both _wputenv_s() and SetEnvironmentVariableW() update the environment
       in the Process Environment Block (PEB), but _wputenv_s() also updates
       the CRT environ and _wenviron variables. Use _wputenv_s() in order to
       be compatible with C libraries that use the CRT variables and the CRT
       functions that use these variables, such as getenv(). */

    errno_t err;
    _Py_BEGIN_SUPPRESS_IPH
    err = _wputenv_s(name, value);
    _Py_END_SUPPRESS_IPH

    if (err) {
        posix_error();
        return NULL;
    }

    Py_RETURN_NONE;
}