self.assertRaises(OSError, os.execvpe, 'no such app-',
['no such app-'], None)
++ def test_execv_with_bad_arglist(self):
++ self.assertRaises(ValueError, os.execv, 'notepad', ())
++ self.assertRaises(ValueError, os.execv, 'notepad', [])
++ self.assertRaises(ValueError, os.execv, 'notepad', ('',))
++ self.assertRaises(ValueError, os.execv, 'notepad', [''])
++
def test_execvpe_with_bad_arglist(self):
self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
++ self.assertRaises(ValueError, os.execvpe, 'notepad', [], {})
++ self.assertRaises(ValueError, os.execvpe, 'notepad', [''], {})
@unittest.skipUnless(hasattr(os, '_execvpe'),
"No internal os._execvpe function to test.")
self.assertEqual(status, (pid, 0))
- def test_spawnl_noargs(self):
+class SpawnTests(unittest.TestCase):
+ def create_args(self, *, with_env=False, use_bytes=False):
+ self.exitcode = 17
+
+ filename = support.TESTFN
+ self.addCleanup(support.unlink, filename)
+
+ if not with_env:
+ code = 'import sys; sys.exit(%s)' % self.exitcode
+ else:
+ self.env = dict(os.environ)
+ # create an unique key
+ self.key = str(uuid.uuid4())
+ self.env[self.key] = self.key
+ # read the variable from os.environ to check that it exists
+ code = ('import sys, os; magic = os.environ[%r]; sys.exit(%s)'
+ % (self.key, self.exitcode))
+
+ with open(filename, "w") as fp:
+ fp.write(code)
+
+ args = [sys.executable, filename]
+ if use_bytes:
+ args = [os.fsencode(a) for a in args]
+ self.env = {os.fsencode(k): os.fsencode(v)
+ for k, v in self.env.items()}
+
+ return args
+
+ @requires_os_func('spawnl')
+ def test_spawnl(self):
+ args = self.create_args()
+ exitcode = os.spawnl(os.P_WAIT, args[0], *args)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnle')
+ def test_spawnle(self):
+ args = self.create_args(with_env=True)
+ exitcode = os.spawnle(os.P_WAIT, args[0], *args, self.env)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnlp')
+ def test_spawnlp(self):
+ args = self.create_args()
+ exitcode = os.spawnlp(os.P_WAIT, args[0], *args)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnlpe')
+ def test_spawnlpe(self):
+ args = self.create_args(with_env=True)
+ exitcode = os.spawnlpe(os.P_WAIT, args[0], *args, self.env)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnv')
+ def test_spawnv(self):
+ args = self.create_args()
+ exitcode = os.spawnv(os.P_WAIT, args[0], args)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnve')
+ def test_spawnve(self):
+ args = self.create_args(with_env=True)
+ exitcode = os.spawnve(os.P_WAIT, args[0], args, self.env)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnvp')
+ def test_spawnvp(self):
+ args = self.create_args()
+ exitcode = os.spawnvp(os.P_WAIT, args[0], args)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnvpe')
+ def test_spawnvpe(self):
+ args = self.create_args(with_env=True)
+ exitcode = os.spawnvpe(os.P_WAIT, args[0], args, self.env)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnv')
+ def test_nowait(self):
+ args = self.create_args()
+ pid = os.spawnv(os.P_NOWAIT, args[0], args)
+ result = os.waitpid(pid, 0)
+ self.assertEqual(result[0], pid)
+ status = result[1]
+ if hasattr(os, 'WIFEXITED'):
+ self.assertTrue(os.WIFEXITED(status))
+ self.assertEqual(os.WEXITSTATUS(status), self.exitcode)
+ else:
+ self.assertEqual(status, self.exitcode << 8)
+
+ @requires_os_func('spawnve')
+ def test_spawnve_bytes(self):
+ # Test bytes handling in parse_arglist and parse_envlist (#28114)
+ args = self.create_args(with_env=True, use_bytes=True)
+ exitcode = os.spawnve(os.P_WAIT, args[0], args, self.env)
+ self.assertEqual(exitcode, self.exitcode)
+
+ @requires_os_func('spawnl')
+ def test_spawnl_noargs(self):
+ args = self.create_args()
+ self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, args[0])
++ self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, args[0], '')
+
+ @requires_os_func('spawnle')
- def test_spawnv_noargs(self):
++ def test_spawnle_noargs(self):
+ args = self.create_args()
+ self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, args[0], {})
++ self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, args[0], '', {})
+
+ @requires_os_func('spawnv')
+ def test_spawnv_noargs(self):
+ args = self.create_args()
+ self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], ())
+ self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], [])
++ self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], ('',))
++ self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], [''])
+
+ @requires_os_func('spawnve')
++ def test_spawnve_noargs(self):
+ args = self.create_args()
+ self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], (), {})
+ self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], [], {})
++ self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], ('',), {})
++ self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], [''], {})
+
# The introduction of this TestCase caused at least two different errors on
# *nix buildbots. Temporarily skip this to let the buildbots move along.
@unittest.skip("Skip due to platform/environment differences on *NIX buildbots")
if (argvlist == NULL) {
return NULL;
}
++ if (!argvlist[0][0]) {
++ PyErr_SetString(PyExc_ValueError,
++ "execv() arg 2 first element cannot be empty");
++ free_string_array(argvlist, argc);
++ return NULL;
++ }
- execv(path_char, argvlist);
++ _Py_BEGIN_SUPPRESS_IPH
+#ifdef HAVE_WEXECV
+ _wexecv(path->wide, argvlist);
+#else
+ execv(path->narrow, argvlist);
+#endif
++ _Py_END_SUPPRESS_IPH
/* If we get here it's definitely an error */
goto fail;
}
argc = PySequence_Size(argv);
++ if (argc < 1) {
++ PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
++ return NULL;
++ }
++
if (!PyMapping_Check(env)) {
PyErr_SetString(PyExc_TypeError,
"execve: environment must be a mapping object");
if (argvlist == NULL) {
goto fail;
}
++ if (!argvlist[0][0]) {
++ PyErr_SetString(PyExc_ValueError,
++ "execve: argv first element cannot be empty");
++ goto fail;
++ }
envlist = parse_envlist(env, &envc);
if (envlist == NULL)
goto fail;
++ _Py_BEGIN_SUPPRESS_IPH
#ifdef HAVE_FEXECVE
if (path->fd > -1)
fexecve(path->fd, argvlist, envlist);
else
#endif
+#ifdef HAVE_WEXECV
+ _wexecve(path->wide, argvlist, envlist);
+#else
execve(path->narrow, argvlist, envlist);
+#endif
++ _Py_END_SUPPRESS_IPH
/* If we get here it's definitely an error */
"spawnv() arg 2 must contain only strings");
return NULL;
}
-#ifdef MS_WINDOWS
+ if (i == 0 && !argvlist[0][0]) {
+ free_string_array(argvlist, i);
+ PyErr_SetString(
+ PyExc_ValueError,
+ "spawnv() arg 2 first element cannot be empty");
+ return NULL;
+ }
-#endif
}
argvlist[argc] = NULL;
lastarg = i;
goto fail_1;
}
++ if (i == 0 && !argvlist[0][0]) {
++ lastarg = i;
++ PyErr_SetString(
++ PyExc_ValueError,
++ "spawnv() arg 2 first element cannot be empty");
++ goto fail_1;
++ }
}
lastarg = argc;
argvlist[argc] = NULL;