Use pipes.quote() rather than manual quoting, and do so consistently wherever shell=True is set.

RELNOTES: None
PiperOrigin-RevId: 197939143
diff --git a/tools/objc/j2objc_dead_code_pruner.py b/tools/objc/j2objc_dead_code_pruner.py
index 4f22259..da42862 100755
--- a/tools/objc/j2objc_dead_code_pruner.py
+++ b/tools/objc/j2objc_dead_code_pruner.py
@@ -29,6 +29,7 @@
 from collections import OrderedDict
 import multiprocessing
 import os
+import pipes  # swap to shlex once on Python 3
 import Queue
 import re
 import shutil
@@ -312,8 +313,8 @@
   Returns:
     A list of basenames of matching members of the given archive
   """
-  ar_contents_cmd = '%s ar -t %s' % (xcrunwrapper, archive)
-  real_object_names = subprocess.check_output(ar_contents_cmd, shell=True)
+  ar_contents_cmd = [xcrunwrapper, 'ar', '-t', archive]
+  real_object_names = subprocess.check_output(ar_contents_cmd)
   expected_object_name_regex = r'^(?:%s)(?:_[0-9a-f]{32}(?:-[0-9]+)?)?\.o$' % (
       '|'.join([re.escape(name) for name in object_names]))
   return re.findall(expected_object_name_regex, real_object_names,
@@ -367,35 +368,35 @@
       # If all objects in the archive are unreachable, just copy over a dummy
       # archive that contains no object
       if len(unreachable_object_names) == len(source_files):
-        j2objc_cmd = 'cp %s %s' % (dummy_archive, output_archive)
+        j2objc_cmd = 'cp %s %s' % (pipes.quote(dummy_archive),
+                                   pipes.quote(output_archive))
       # Else we need to prune the archive of unreachable objects
       else:
         cmd_env['ZERO_AR_DATE'] = '1'
         # Copy the input archive to the output location
-        j2objc_cmd += 'cp %s %s && ' % (input_archive, output_archive)
+        j2objc_cmd += 'cp %s %s && ' % (pipes.quote(input_archive),
+                                        pipes.quote(output_archive))
         # Make the output archive editable
-        j2objc_cmd += 'chmod +w %s && ' % (output_archive)
+        j2objc_cmd += 'chmod +w %s && ' % (pipes.quote(output_archive))
         # Remove the unreachable objects from the archive
         unreachable_object_names = MatchObjectNamesInArchive(
             xcrunwrapper, input_archive, unreachable_object_names)
-        # We need to quote the object names because they may contains special
-        # shell characters.
-        quoted_unreachable_object_names = [
-            "'" + unreachable_object_name + "'"
-            for unreachable_object_name in unreachable_object_names]
         j2objc_cmd += '%s ar -d -s %s %s && ' % (
-            xcrunwrapper,
-            output_archive,
-            ' '.join(quoted_unreachable_object_names))
+            pipes.quote(xcrunwrapper),
+            pipes.quote(output_archive),
+            ' '.join(pipes.quote(uon) for uon in unreachable_object_names))
         # Update the table of content of the archive file
-        j2objc_cmd += '%s ranlib %s' % (xcrunwrapper, output_archive)
+        j2objc_cmd += '%s ranlib %s' % (pipes.quote(xcrunwrapper),
+                                        pipes.quote(output_archive))
     # There are no unreachable objects, we just copy over the original archive
     else:
-      j2objc_cmd = 'cp %s %s' % (input_archive, output_archive)
+      j2objc_cmd = 'cp %s %s' % (pipes.quote(input_archive),
+                                 pipes.quote(output_archive))
   # The archive cannot be pruned by J2ObjC dead code removal, just copy over
   # the original archive
   else:
-    j2objc_cmd = 'cp %s %s' % (input_archive, output_archive)
+    j2objc_cmd = 'cp %s %s' % (pipes.quote(input_archive),
+                               pipes.quote(output_archive))
 
   subprocess.check_output(
       j2objc_cmd, stderr=subprocess.STDOUT, shell=True, env=cmd_env)