mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 11:14:38 +08:00
Default absent CreateProcess startup attributes (#9267)
* Default missing CreateProcess startup attributes Assisted-by: Codex:GPT-6 * Use a single platform guard for winapi tests Assisted-by: Codex:GPT-6
This commit is contained in:
1 parent
97bd4af533
commit
bd85943b62
2 files changed
+102
-41
No files matched your search
@@ -246,20 +246,25 @@ mod _winapi {
|
||||
args: CreateProcessArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<(WinHandle, WinHandle, u32, u32)> {
|
||||
// Default failed startup attribute lookups as CPython does. Keep value
|
||||
// conversion errors separate from lookup failures.
|
||||
macro_rules! si_attr {
|
||||
($attr:ident, $t:ty) => {{
|
||||
<Option<$t>>::try_from_object(
|
||||
vm,
|
||||
args.startup_info.get_attr(stringify!($attr), vm)?,
|
||||
)?
|
||||
.unwrap_or(0) as _
|
||||
args.startup_info
|
||||
.get_attr(stringify!($attr), vm)
|
||||
.ok()
|
||||
.map(|obj| <Option<$t>>::try_from_object(vm, obj))
|
||||
.transpose()?
|
||||
.flatten()
|
||||
.unwrap_or(0) as _
|
||||
}};
|
||||
($attr:ident) => {{
|
||||
<Option<_>>::try_from_object(
|
||||
vm,
|
||||
args.startup_info.get_attr(stringify!($attr), vm)?,
|
||||
)?
|
||||
.unwrap_or(0)
|
||||
args.startup_info
|
||||
.get_attr(stringify!($attr), vm)
|
||||
.ok()
|
||||
.map(|obj| TryFromObject::try_from_object(vm, obj))
|
||||
.transpose()?
|
||||
.unwrap_or(0)
|
||||
}};
|
||||
}
|
||||
let startup_info = host_winapi::StartupInfoData {
|
||||
@@ -275,7 +280,13 @@ mod _winapi {
|
||||
.map(|m| getenvironment(m, vm))
|
||||
.transpose()?;
|
||||
|
||||
let handle_list = get_handle_list(args.startup_info.get_attr("lpAttributeList", vm)?, vm)?;
|
||||
let handle_list = args
|
||||
.startup_info
|
||||
.get_attr("lpAttributeList", vm)
|
||||
.ok()
|
||||
.map(|obj| get_handle_list(obj, vm))
|
||||
.transpose()?
|
||||
.flatten();
|
||||
|
||||
// Validate no embedded null bytes in command name and command line
|
||||
// before handing the strings off; to_wide_cstring rejects interior NULs.
|
||||
|
||||
@@ -4,36 +4,86 @@ import sys
|
||||
|
||||
from testutils import assert_raises
|
||||
|
||||
if sys.platform == "win32":
|
||||
import _winapi
|
||||
if sys.platform != "win32":
|
||||
sys.exit(0)
|
||||
|
||||
# Every call fails before a host operation. ReportEvent overflow cases
|
||||
# also retain an embedded NUL as an independent safety barrier.
|
||||
assert _winapi.EVENTLOG_SUCCESS == 0
|
||||
assert _winapi.EVENTLOG_ERROR_TYPE == 1
|
||||
assert _winapi.EVENTLOG_WARNING_TYPE == 2
|
||||
assert _winapi.EVENTLOG_INFORMATION_TYPE == 4
|
||||
assert _winapi.EVENTLOG_AUDIT_SUCCESS == 8
|
||||
assert _winapi.EVENTLOG_AUDIT_FAILURE == 16
|
||||
import _winapi
|
||||
|
||||
assert_raises(TypeError, _winapi.RegisterEventSource, 1, "source\0")
|
||||
assert_raises(TypeError, _winapi.RegisterEventSource, None, 1)
|
||||
assert_raises(TypeError, _winapi.RegisterEventSource, None, None)
|
||||
assert_raises(ValueError, _winapi.RegisterEventSource, None, "source\0")
|
||||
assert_raises(ValueError, _winapi.RegisterEventSource, "server\0", "source\0")
|
||||
assert_raises(ValueError, _winapi.RegisterEventSource, "", "source\0")
|
||||
assert_raises(TypeError, _winapi.DeregisterEventSource, "invalid handle")
|
||||
assert_raises(TypeError, _winapi.DeregisterEventSource, None)
|
||||
assert_raises(
|
||||
TypeError, _winapi.ReportEvent, "invalid handle", 0, 0, 0, "message\0"
|
||||
)
|
||||
assert_raises(ValueError, _winapi.ReportEvent, 0, 0, 0, 0, "message\0")
|
||||
assert_raises(TypeError, _winapi.ReportEvent, 0, 0, 0, 0, None)
|
||||
for index, bits in ((1, 16), (2, 16), (3, 32)):
|
||||
for invalid, exception in ((-1, ValueError), (1 << bits, OverflowError)):
|
||||
arguments = [0, 0, 0, 0, "message\0"]
|
||||
arguments[index] = invalid
|
||||
assert_raises(exception, _winapi.ReportEvent, *arguments)
|
||||
# Every call fails before a host operation. ReportEvent overflow cases
|
||||
# also retain an embedded NUL as an independent safety barrier.
|
||||
assert _winapi.EVENTLOG_SUCCESS == 0
|
||||
assert _winapi.EVENTLOG_ERROR_TYPE == 1
|
||||
assert _winapi.EVENTLOG_WARNING_TYPE == 2
|
||||
assert _winapi.EVENTLOG_INFORMATION_TYPE == 4
|
||||
assert _winapi.EVENTLOG_AUDIT_SUCCESS == 8
|
||||
assert _winapi.EVENTLOG_AUDIT_FAILURE == 16
|
||||
|
||||
assert_raises(TypeError, _winapi.RegisterEventSource, 1, "source\0")
|
||||
assert_raises(TypeError, _winapi.RegisterEventSource, None, 1)
|
||||
assert_raises(TypeError, _winapi.RegisterEventSource, None, None)
|
||||
assert_raises(ValueError, _winapi.RegisterEventSource, None, "source\0")
|
||||
assert_raises(ValueError, _winapi.RegisterEventSource, "server\0", "source\0")
|
||||
assert_raises(ValueError, _winapi.RegisterEventSource, "", "source\0")
|
||||
assert_raises(TypeError, _winapi.DeregisterEventSource, "invalid handle")
|
||||
assert_raises(TypeError, _winapi.DeregisterEventSource, None)
|
||||
assert_raises(TypeError, _winapi.ReportEvent, "invalid handle", 0, 0, 0, "message\0")
|
||||
assert_raises(ValueError, _winapi.ReportEvent, 0, 0, 0, 0, "message\0")
|
||||
assert_raises(TypeError, _winapi.ReportEvent, 0, 0, 0, 0, None)
|
||||
for index, bits in ((1, 16), (2, 16), (3, 32)):
|
||||
for invalid, exception in ((-1, ValueError), (1 << bits, OverflowError)):
|
||||
arguments = [0, 0, 0, 0, "message\0"]
|
||||
arguments[index] = "invalid integer"
|
||||
assert_raises(TypeError, _winapi.ReportEvent, *arguments)
|
||||
arguments[index] = invalid
|
||||
assert_raises(exception, _winapi.ReportEvent, *arguments)
|
||||
arguments = [0, 0, 0, 0, "message\0"]
|
||||
arguments[index] = "invalid integer"
|
||||
assert_raises(TypeError, _winapi.ReportEvent, *arguments)
|
||||
|
||||
|
||||
import subprocess
|
||||
|
||||
|
||||
class PartialStartupInfo:
|
||||
dwFlags = 0
|
||||
|
||||
def __getattr__(self, name):
|
||||
raise ValueError(name)
|
||||
|
||||
|
||||
for startup in (None, PartialStartupInfo()):
|
||||
process, thread, _, _ = _winapi.CreateProcess(
|
||||
sys.executable,
|
||||
subprocess.list2cmdline([sys.executable, "-c", "pass"]),
|
||||
None,
|
||||
None,
|
||||
False,
|
||||
_winapi.CREATE_NO_WINDOW,
|
||||
None,
|
||||
None,
|
||||
startup,
|
||||
)
|
||||
try:
|
||||
status = _winapi.WaitForSingleObject(process, 10000)
|
||||
if status != _winapi.WAIT_OBJECT_0:
|
||||
_winapi.TerminateProcess(process, 1)
|
||||
_winapi.WaitForSingleObject(process, 10000)
|
||||
assert status == _winapi.WAIT_OBJECT_0
|
||||
assert _winapi.GetExitCodeProcess(process) == 0
|
||||
finally:
|
||||
_winapi.CloseHandle(thread)
|
||||
_winapi.CloseHandle(process)
|
||||
|
||||
startup = subprocess.STARTUPINFO()
|
||||
startup.dwFlags = "invalid"
|
||||
assert_raises(
|
||||
TypeError,
|
||||
_winapi.CreateProcess,
|
||||
None,
|
||||
"invalid\0",
|
||||
None,
|
||||
None,
|
||||
False,
|
||||
0,
|
||||
None,
|
||||
None,
|
||||
startup,
|
||||
)
|
||||
Reference in new issue
Block a user