(
path: OsPath,
argv: Either<PyListRef, PyTupleRef>,
env: ArgMapping,
vm: &VirtualMachine,
)
| 1217 | #[cfg(target_env = "msvc")] |
| 1218 | #[pyfunction] |
| 1219 | fn execve( |
| 1220 | path: OsPath, |
| 1221 | argv: Either<PyListRef, PyTupleRef>, |
| 1222 | env: ArgMapping, |
| 1223 | vm: &VirtualMachine, |
| 1224 | ) -> PyResult<()> { |
| 1225 | use core::iter::once; |
| 1226 | |
| 1227 | let make_widestring = |
| 1228 | |s: &str| widestring::WideCString::from_os_str(s).map_err(|err| err.to_pyexception(vm)); |
| 1229 | |
| 1230 | let path = path.to_wide_cstring(vm)?; |
| 1231 | |
| 1232 | let argv = vm.extract_elements_with(argv.as_ref(), |obj| { |
| 1233 | let arg = PyStrRef::try_from_object(vm, obj)?; |
| 1234 | make_widestring(arg.expect_str()) |
| 1235 | })?; |
| 1236 | |
| 1237 | let first = argv |
| 1238 | .first() |
| 1239 | .ok_or_else(|| vm.new_value_error("execve: argv must not be empty"))?; |
| 1240 | |
| 1241 | if first.is_empty() { |
| 1242 | return Err(vm.new_value_error("execve: argv first element cannot be empty")); |
| 1243 | } |
| 1244 | |
| 1245 | let argv_execve: Vec<*const u16> = argv |
| 1246 | .iter() |
| 1247 | .map(|v| v.as_ptr()) |
| 1248 | .chain(once(core::ptr::null())) |
| 1249 | .collect(); |
| 1250 | |
| 1251 | let env = crate::stdlib::os::envobj_to_dict(env, vm)?; |
| 1252 | // Build environment strings as "KEY=VALUE\0" wide strings |
| 1253 | let mut env_strings: Vec<widestring::WideCString> = Vec::new(); |
| 1254 | for (key, value) in env.into_iter() { |
| 1255 | let key = PyStrRef::try_from_object(vm, key)?; |
| 1256 | let value = PyStrRef::try_from_object(vm, value)?; |
| 1257 | let key_str = key.expect_str(); |
| 1258 | let value_str = value.expect_str(); |
| 1259 | |
| 1260 | // Validate: no null characters in key or value |
| 1261 | if key_str.contains('\0') || value_str.contains('\0') { |
| 1262 | return Err(vm.new_value_error("embedded null character")); |
| 1263 | } |
| 1264 | // Validate: empty key or '=' in key after position 0 |
| 1265 | // (search from index 1 because on Windows starting '=' is allowed |
| 1266 | // for defining hidden environment variables) |
| 1267 | if key_str.is_empty() || key_str.get(1..).is_some_and(|s| s.contains('=')) { |
| 1268 | return Err(vm.new_value_error("illegal environment variable name")); |
| 1269 | } |
| 1270 | |
| 1271 | let env_str = format!("{}={}", key_str, value_str); |
| 1272 | env_strings.push(make_widestring(&env_str)?); |
| 1273 | } |
| 1274 | |
| 1275 | let envp: Vec<*const u16> = env_strings |
| 1276 | .iter() |
no test coverage detected