diff options
4 files changed, 94 insertions, 43 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py b/lldb/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py index 3131000be42..0eeb6ff9379 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py @@ -4,12 +4,15 @@ Test lldb process launch flags. from __future__ import print_function +import copy +import os +import time - -import os, time import lldb from lldbsuite.test.lldbtest import * +import six + class ProcessLaunchTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @@ -17,9 +20,18 @@ class ProcessLaunchTestCase(TestBase): def setUp(self): # Call super's setUp(). TestBase.setUp(self) + self.stdout_redirect_file = 'lldb-stdout-redirect.txt' # disable "There is a running process, kill it and restart?" prompt self.runCmd("settings set auto-confirm true") - self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm")) + def tearDown(self): + self.runCmd("settings clear auto-confirm") + + try: + os.unlink(self.stdout_redirect_file) + except: + pass + + super().tearDown() @not_remote_testsuite_ready def test_io (self): @@ -180,8 +192,9 @@ class ProcessLaunchTestCase(TestBase): self.fail(err_msg) def test_environment_with_special_char (self): - """Test that environment variables containing '*' and '}' are communicated correctly to the lldb-server.""" - d = {'CXX_SOURCES' : 'print_env.cpp'} + """Test that environment variables containing '*' and '}' are handled correctly by the inferior.""" + source = 'print_env.cpp' + d = {'CXX_SOURCES' : source} self.build(dictionary=d) self.setTearDownCleanup(d) exe = os.path.join (os.getcwd(), "a.out") @@ -189,19 +202,19 @@ class ProcessLaunchTestCase(TestBase): evil_var = 'INIT*MIDDLE}TAIL' target = self.dbg.CreateTarget(exe) - process = target.LaunchSimple(None, ['EVIL=' + evil_var], self.get_process_working_directory()) - self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) - - out = process.GetSTDOUT(len(evil_var)) - self.assertIsNotNone(out, "Encountered an error reading the process's output") + main_source_spec = lldb.SBFileSpec(source) + breakpoint = target.BreakpointCreateBySourceRegex('// Set breakpoint here.', main_source_spec) - out = out[:len(evil_var)] - if out != evil_var: - self.fail('The environment variable was mis-coded: %s\n' % repr(out)) + process = target.LaunchSimple(None, ['EVIL=' + evil_var], self.get_process_working_directory()) + self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) - newline = process.GetSTDOUT(1) - self.assertIsNotNone(newline, "Encountered an error reading the process's output") + threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertEqual(len(threads), 1) + frame = threads[0].GetFrameAtIndex(0) + sbvalue = frame.EvaluateExpression("evil") + value = sbvalue.GetSummary().strip('"') - newline = newline[0] - if newline != '\r' and newline != '\n': - self.fail('Garbage at end of environment variable') + self.assertEqual(value, evil_var) + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) + pass
\ No newline at end of file diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp index cbb9b217591..8c6df8ea01a 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp @@ -5,7 +5,6 @@ int main (int argc, char **argv) { char *evil = getenv("EVIL"); - puts(evil); - return 0; + return 0; // Set breakpoint here. } diff --git a/lldb/scripts/Python/python-typemaps.swig b/lldb/scripts/Python/python-typemaps.swig index 68e442defd3..ca918198863 100644 --- a/lldb/scripts/Python/python-typemaps.swig +++ b/lldb/scripts/Python/python-typemaps.swig @@ -1,20 +1,22 @@ /* Typemap definitions, to allow SWIG to properly handle 'char**' data types. */ %typemap(in) char ** { + using namespace lldb_private; /* Check if is a list */ - if (PyList_Check($input)) { - int size = PyList_Size($input); + if (PythonList::Check($input)) { + PythonList list(PyRefType::Borrowed, $input); + int size = list.GetSize(); int i = 0; - $1 = (char **) malloc((size+1) * sizeof(char*)); + $1 = (char**)malloc((size+1)*sizeof(char*)); for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyString_Check(o)) - $1[i] = PyString_AsString(o); - else { + PythonString py_str = list.GetItemAtIndex(i).AsType<PythonString>(); + if (!py_str.IsAllocated()) { PyErr_SetString(PyExc_TypeError,"list must contain strings"); free($1); - return NULL; + return nullptr; } + + $1[i] = const_cast<char*>(py_str.GetString().data()); } $1[i] = 0; } else if ($input == Py_None) { @@ -42,12 +44,14 @@ %typemap(typecheck) char ** { /* Check if is a list */ $1 = 1; - if (PyList_Check($input)) { - int size = PyList_Size($input); + using namespace lldb_private; + if (PythonList::Check($input)) { + PythonList list(PyRefType::Borrowed, $input); + int size = list.GetSize(); int i = 0; for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (!PyString_Check(o)) { $1 = 0; } + PythonString s = list.GetItemAtIndex(i).AsType<PythonString>(); + if (!s.IsAllocated()) { $1 = 0; } } } else @@ -81,13 +85,12 @@ $1 = (char**)malloc((size+1)*sizeof(char*)); for (int i = 0; i < size; i++) { - PythonObject o = py_list.GetItemAtIndex(i); - if (!PythonString::Check(o.get())) { + auto py_str = py_list.GetItemAtIndex(i).AsType<PythonString>(); + if (!py_str.IsAllocated()) { PyErr_SetString(PyExc_TypeError,"list must contain strings"); free($1); return nullptr; } - auto py_str = o.AsType<PythonString>(); $1[i] = const_cast<char*>(py_str.GetString().data()); } @@ -101,14 +104,16 @@ } %typemap(typecheck) char const ** { + using namespace lldb_private; /* Check if is a list */ $1 = 1; - if (PyList_Check($input)) { - int size = PyList_Size($input); + if (PythonList::Check($input)) { + PythonList list(PyRefType::Borrowed, $input); + int size = list.GetSize(); int i = 0; for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (!PyString_Check(o)) { $1 = 0; } + PythonString s = list.GetItemAtIndex(i).AsType<PythonString>(); + if (!s.IsAllocated()) { $1 = 0; } } } else @@ -126,10 +131,13 @@ int i; len = 0; while ($1[len]) len++; - $result = PyList_New(len); + using namespace lldb_private; + PythonList list(len); for (i = 0; i < len; i++) { - PyList_SetItem($result, i, PyString_FromString($1[i])); + PythonString str($1[i]); + list.SetItemAtIndex(i, str); } + $result = list.release(); } /* Typemap definitions to allow SWIG to properly handle char buffer. */ diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp index 355dd40544f..a99faa227f7 100644 --- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp +++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp @@ -17,6 +17,31 @@ using namespace lldb; using namespace lldb_private; +namespace +{ +void +CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) +{ + if (env.GetArgumentCount() == 0) + return; + + int bytes = 0; + for (int i = 0; i < env.GetArgumentCount(); ++i) + bytes += strlen(env.GetArgumentAtIndex(i)) + sizeof(char); + bytes += sizeof(char); + buffer.resize(bytes); + char *cur_entry = &buffer[0]; + for (int i = 0; i < env.GetArgumentCount(); ++i) + { + ::strcpy(cur_entry, env.GetArgumentAtIndex(i)); + cur_entry += strlen(cur_entry) + sizeof(char); + } + // Environment buffer is a null terminated list of null terminated + // strings, so it is terminated by two null bytes. + buffer.back() = 0; +} +} + HostProcess ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) { @@ -49,10 +74,16 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Erro if (launch_info.GetFlags().Test(eLaunchFlagDebug)) flags |= DEBUG_ONLY_THIS_PROCESS; + auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries()); + LPVOID env_block = nullptr; + ::CreateEnvironmentBuffer(env, environment); + if (!environment.empty()) + env_block = environment.data(); + executable = launch_info.GetExecutableFile().GetPath(); launch_info.GetArguments().GetQuotedCommandString(commandLine); - BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags, NULL, - launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi); + BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags, + env_block, launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi); if (result) { // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. |