[Lldb-commits] [lldb] r265357 - Improve the way LLDB escapes arguments before passing them to the shell

Enrico Granata via lldb-commits lldb-commits at lists.llvm.org
Mon Apr 4 15:46:40 PDT 2016


Author: enrico
Date: Mon Apr  4 17:46:38 2016
New Revision: 265357

URL: http://llvm.org/viewvc/llvm-project?rev=265357&view=rev
Log:
Improve the way LLDB escapes arguments before passing them to the shell

Teach LLDB that different shells have different characters they are sensitive to, and use that knowledge to do shell-aware escaping

This helps solve a class of problems on OS X where LLDB would try to launch via sh, and run into problems if the command line being passed to the inferior contained such special markers (hint: the shell would error out and we'd fail to launch)
This makes those launch scenarios work transparently via shell expansion

Slightly improve the error message when this kind of failure occurs to at least suggest that the user try going through 'process launch' directly

Fixes rdar://problem/22749408


Modified:
    lldb/trunk/include/lldb/API/SBLaunchInfo.h
    lldb/trunk/include/lldb/Interpreter/Args.h
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py
    lldb/trunk/source/Interpreter/Args.cpp
    lldb/trunk/source/Target/Platform.cpp
    lldb/trunk/source/Target/ProcessLaunchInfo.cpp

Modified: lldb/trunk/include/lldb/API/SBLaunchInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBLaunchInfo.h?rev=265357&r1=265356&r2=265357&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBLaunchInfo.h (original)
+++ lldb/trunk/include/lldb/API/SBLaunchInfo.h Mon Apr  4 17:46:38 2016
@@ -145,7 +145,7 @@ public:
     GetShellExpandArguments ();
     
     void
-    SetShellExpandArguments (bool glob);
+    SetShellExpandArguments (bool expand);
     
     uint32_t
     GetResumeCount ();

Modified: lldb/trunk/include/lldb/Interpreter/Args.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/Args.h?rev=265357&r1=265356&r2=265357&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/Args.h (original)
+++ lldb/trunk/include/lldb/Interpreter/Args.h Mon Apr  4 17:46:38 2016
@@ -403,7 +403,7 @@ public:
     StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update);
 
     static const char *
-    GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg);
+    GetShellSafeArgument (const FileSpec& shell, const char *unsafe_arg, std::string &safe_arg);
 
     // EncodeEscapeSequences will change the textual representation of common
     // escape sequences like "\n" (two characters) into a single '\n'. It does

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py?rev=265357&r1=265356&r2=265357&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py Mon Apr  4 17:46:38 2016
@@ -30,7 +30,7 @@ class LaunchWithShellExpandTestCase(Test
         breakpoint = target.BreakpointCreateBySourceRegex ('break here', lldb.SBFileSpec ("main.cpp", False))
         self.assertTrue(breakpoint, VALID_BREAKPOINT)
 
-        self.runCmd("process launch -X true -w %s -- fi*.tx?" % (os.getcwd()))
+        self.runCmd("process launch -X true -w %s -- fi*.tx? () > <" % (os.getcwd()))
 
         process = self.process()
 
@@ -51,7 +51,11 @@ class LaunchWithShellExpandTestCase(Test
         self.expect("frame variable argv[2]", substrs=['file2.txt'])
         self.expect("frame variable argv[3]", substrs=['file3.txt'])
         self.expect("frame variable argv[4]", substrs=['file4.txy'])
+        self.expect("frame variable argv[5]", substrs=['()'])
+        self.expect("frame variable argv[6]", substrs=['>'])
+        self.expect("frame variable argv[7]", substrs=['<'])
         self.expect("frame variable argv[5]", substrs=['file5.tyx'], matching=False)
+        self.expect("frame variable argv[8]", substrs=['file5.tyx'], matching=False)
 
         self.runCmd("process kill")
 

Modified: lldb/trunk/source/Interpreter/Args.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Args.cpp?rev=265357&r1=265356&r2=265357&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/Args.cpp (original)
+++ lldb/trunk/source/Interpreter/Args.cpp Mon Apr  4 17:46:38 2016
@@ -887,14 +887,43 @@ Args::StringToVersion (const char *s, ui
 }
 
 const char *
-Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
+Args::GetShellSafeArgument (const FileSpec& shell,
+                            const char *unsafe_arg,
+                            std::string &safe_arg)
 {
+    struct ShellDescriptor
+    {
+        ConstString m_basename;
+        const char* m_escapables;
+    };
+    
+    static ShellDescriptor g_Shells[] = {
+        {ConstString("bash")," '\"<>()&"},
+        {ConstString("tcsh")," '\"<>()&$"},
+        {ConstString("sh")," '\"<>()&"}
+    };
+    
+    // safe minimal set
+    const char* escapables = " '\"";
+    
+    if (auto basename = shell.GetFilename())
+    {
+        for (const auto& Shell : g_Shells)
+        {
+            if (Shell.m_basename == basename)
+            {
+                escapables = Shell.m_escapables;
+                break;
+            }
+        }
+    }
+
     safe_arg.assign (unsafe_arg);
     size_t prev_pos = 0;
     while (prev_pos < safe_arg.size())
     {
         // Escape spaces and quotes
-        size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
+        size_t pos = safe_arg.find_first_of(escapables, prev_pos);
         if (pos != std::string::npos)
         {
             safe_arg.insert (pos, 1, '\\');
@@ -906,7 +935,6 @@ Args::GetShellSafeArgument (const char *
     return safe_arg.c_str();
 }
 
-
 int64_t
 Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
 {    

Modified: lldb/trunk/source/Target/Platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Platform.cpp?rev=265357&r1=265356&r2=265357&view=diff
==============================================================================
--- lldb/trunk/source/Target/Platform.cpp (original)
+++ lldb/trunk/source/Target/Platform.cpp Mon Apr  4 17:46:38 2016
@@ -1241,7 +1241,11 @@ Platform::LaunchProcess (ProcessLaunchIn
         {
             error = ShellExpandArguments(launch_info);
             if (error.Fail())
+            {
+                error.SetErrorStringWithFormat("shell expansion failed (reason: %s). consider launching with 'process launch'.",
+                                               error.AsCString("unknown"));
                 return error;
+            }
         }
 
         if (log)

Modified: lldb/trunk/source/Target/ProcessLaunchInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ProcessLaunchInfo.cpp?rev=265357&r1=265356&r2=265357&view=diff
==============================================================================
--- lldb/trunk/source/Target/ProcessLaunchInfo.cpp (original)
+++ lldb/trunk/source/Target/ProcessLaunchInfo.cpp Mon Apr  4 17:46:38 2016
@@ -503,7 +503,9 @@ ProcessLaunchInfo::ConvertArgumentsForLa
             {
                 for (size_t i=0; argv[i] != nullptr; ++i)
                 {
-                    const char *arg = Args::GetShellSafeArgument (argv[i], safe_arg);
+                    const char *arg = Args::GetShellSafeArgument (m_shell,
+                                                                  argv[i],
+                                                                  safe_arg);
                     shell_command.Printf(" %s", arg);
                 }
             }




More information about the lldb-commits mailing list