@@ -73,6 +73,9 @@ module Shellwords
7373 # argv = Shellwords.split('here are "two words"')
7474 # argv #=> ["here", "are", "two words"]
7575 #
76+ # +line+ must not contain NUL characters because of nature of
77+ # +exec+ system call.
78+ #
7679 # Note, however, that this is not a command line parser. Shell
7780 # metacharacters except for the single and double quotes and
7881 # backslash are not treated as such.
@@ -87,9 +90,14 @@ module Shellwords
8790 def shellsplit ( line )
8891 words = [ ]
8992 field = String . new
90- line . scan ( /\G \s *(?>([^\s \\ \' \" ]+)|'([^\' ]*)'|"((?:[^\" \\ ]|\\ . )*)"|(\\ . ?)|(\S ))(\s |\z )?/m ) do
93+ line . scan ( /\G \s *(?>([^\0 \ s\\ \' \" ]+)|'([^\0 \ ' ]*)'|"((?:[^\0 \ "\\ ]|\\ [^ \0 ] )*)"|(\\ [^ \0 ] ?)|(\S ))(\s |\z )?/m ) do
9194 |word , sq , dq , esc , garbage , sep |
92- raise ArgumentError , "Unmatched quote: #{ line . inspect } " if garbage
95+ if garbage
96+ b = $~. begin ( 0 )
97+ line = $~[ 0 ]
98+ line = "..." + line if b > 0
99+ raise ArgumentError , "#{ garbage == "\0 " ? 'Nul character' : 'Unmatched quote' } at #{ b } : #{ line } "
100+ end
93101 # 2.2.3 Double-Quotes:
94102 #
95103 # The <backslash> shall retain its special meaning as an
@@ -118,6 +126,9 @@ class << self
118126 # command line. +str+ can be a non-string object that responds to
119127 # +to_s+.
120128 #
129+ # +str+ must not contain NUL characters because of nature of +exec+
130+ # system call.
131+ #
121132 # Note that a resulted string should be used unquoted and is not
122133 # intended for use in double quotes nor in single quotes.
123134 #
@@ -150,6 +161,9 @@ def shellescape(str)
150161 # An empty argument will be skipped, so return empty quotes.
151162 return "''" . dup if str . empty?
152163
164+ # Shellwords cannot contain NUL characters.
165+ raise ArgumentError , "NUL character" if str . index ( "\0 " )
166+
153167 str = str . dup
154168
155169 # Treat multibyte characters as is. It is the caller's responsibility
@@ -175,6 +189,7 @@ class << self
175189 # All elements are joined into a single string with fields separated by a
176190 # space, where each element is escaped for the Bourne shell and stringified
177191 # using +to_s+.
192+ # See also Shellwords.shellescape.
178193 #
179194 # ary = ["There's", "a", "time", "and", "place", "for", "everything"]
180195 # argv = Shellwords.join(ary)
0 commit comments