[前][次][番号順一覧][スレッド一覧]

ruby-changes:44500

From: knu <ko1@a...>
Date: Sat, 5 Nov 2016 13:58:53 +0900 (JST)
Subject: [ruby-changes:44500] knu:r56573 (trunk): Fix the handling of the backslash in double quotes

knu	2016-11-05 13:58:48 +0900 (Sat, 05 Nov 2016)

  New Revision: 56573

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=56573

  Log:
    Fix the handling of the backslash in double quotes
    
    * lib/shellwords.rb (Shellwords#shellsplit): Fix the handling of
      the backslash in double quotes to conform to the standard.
      [ruby-core:63807] [Bug #10055]

  Modified files:
    trunk/ChangeLog
    trunk/lib/shellwords.rb
    trunk/test/test_shellwords.rb
Index: lib/shellwords.rb
===================================================================
--- lib/shellwords.rb	(revision 56572)
+++ lib/shellwords.rb	(revision 56573)
@@ -6,7 +6,8 @@ https://github.com/ruby/ruby/blob/trunk/lib/shellwords.rb#L6
 # of the UNIX Bourne shell.
 #
 # The shellwords() function was originally a port of shellwords.pl,
-# but modified to conform to POSIX / SUSv3 (IEEE Std 1003.1-2001 [1]).
+# but modified to conform to the Shell & Utilities volume of the IEEE
+# Std 1003.1-2008, 2016 Edition [1].
 #
 # === Usage
 #
@@ -55,7 +56,7 @@ https://github.com/ruby/ruby/blob/trunk/lib/shellwords.rb#L56
 #
 # === Resources
 #
-# 1: {IEEE Std 1003.1-2004}[http://pubs.opengroup.org/onlinepubs/009695399/toc.htm]
+# 1: {IEEE Std 1003.1-2008, 2016 Edition, the Shell & Utilities volume}[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html]
 
 module Shellwords
   # Splits a string into an array of tokens in the same way the UNIX
@@ -81,7 +82,14 @@ module Shellwords https://github.com/ruby/ruby/blob/trunk/lib/shellwords.rb#L82
     line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
       |word, sq, dq, esc, garbage, sep|
       raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage
-      field << (word || sq || (dq || esc).gsub(/\\(.)/, '\\1'))
+      # 2.2.3 Double-Quotes:
+      #
+      #   The <backslash> shall retain its special meaning as an
+      #   escape character only when followed by one of the following
+      #   characters when considered special:
+      #
+      #   $ ` " \ <newline>
+      field << (word || sq || (dq && dq.gsub(/\\([$`"\\\n])/, '\\1')) || esc.gsub(/\\(.)/, '\\1'))
       if sep
         words << field
         field = String.new
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 56572)
+++ ChangeLog	(revision 56573)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Nov  5 13:52:52 2016  Akinori MUSHA  <knu@i...>
+
+	* lib/shellwords.rb (Shellwords#shellsplit): Fix the handling of
+	  the backslash in double quotes to conform to the standard.
+	  [ruby-core:63807] [Bug #10055]
+
 Sat Nov  5 12:14:31 2016  Tanaka Akira  <akr@f...>
 
 	* ext/pathname/pathname.c (Pathname#empty?): New method.
Index: test/test_shellwords.rb
===================================================================
--- test/test_shellwords.rb	(revision 56572)
+++ test/test_shellwords.rb	(revision 56573)
@@ -40,12 +40,24 @@ class TestShellwords < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/test_shellwords.rb#L40
   end
 
   def test_backslashes
-    cmdline, expected = [
-      %q{/a//b///c////d/////e/ "/a//b///c////d/////e/ "'/a//b///c////d/////e/ '/a//b///c////d/////e/ },
-      %q{a/b/c//d//e a/b/c//d//e /a//b///c////d/////e/ a/b/c//d//e }
-    ].map { |str| str.tr("/", "\\\\") }
 
-    assert_equal [expected], shellwords(cmdline)
+    [
+      [
+        %q{/a//b///c////d/////e/ "/a//b///c////d/////e/ "'/a//b///c////d/////e/ '/a//b///c////d/////e/ },
+        'a/b/c//d//e /a/b//c//d///e/ /a//b///c////d/////e/ a/b/c//d//e '
+      ],
+      [
+        %q{printf %s /"/$/`///"/r/n},
+        'printf', '%s', '"$`/"rn'
+      ],
+      [
+        %q{printf %s "/"/$/`///"/r/n"},
+        'printf', '%s', '"$`/"/r/n'
+      ]
+    ].map { |strs|
+      cmdline, *expected = strs.map { |str| str.tr("/", "\\\\") }
+      assert_equal expected, shellwords(cmdline)
+    }
   end
 
   def test_stringification

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]