The dangers of single line regular expressions
greg.molnar.io
The dangers of single line regular expressions
1–10 of 133 posts
Re: The dangers of single line regular expressions
#2Re: The dangers of single line regular expressions
#3But I guess this is why Python has so many ways of matching a pattern against a string (match, find, findall, I think - they are hard to remember)
Re: The dangers of single line regular expressions
#4Even better, compare that to the original and fail validation if they're not identical, but that requires maintaining a higher level of paranoia than may be reasonable to expect.
Re: The dangers of single line regular expressions
#5More like "the danger of thinking you can trivially validate user-supplied input" before evaluating the string.
The bigger problem here is executing user input.
Re: The dangers of single line regular expressions
#6Ruby seems to be in multiline mode all the time?
$ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foobar") else "no"'
yes
$ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\nbar") else "no"'
no
$ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\nbar", re.M) else "no"'
yes
$ perl -le 'print "foobar" =~ /^[a-z ]+$/ ? "yes" : "no"'
yes
$ perl -le 'print "foo\nbar" =~ /^[a-z ]+$/ ? "yes" : "no"'
no
$ perl -le 'print "foo\nbar" =~ /^[a-z ]+$/m ? "yes" : "no"'
yes
$ node -e 'console.log(/^[a-z ]+$/.test("foobar") ? "yes" : "no")'
yes
$ node -e 'console.log(/^[a-z ]+$/.test("foo\nbar") ? "yes" : "no")'
no
$ node -e 'console.log(/^[a-z ]+$/m.test("foo\nbar") ? "yes" : "no")'
yes
$ ruby -e 'if "foobar" =~ /^[0-9a-z ]+$/i then puts "yes" else puts "no" end'
yes
$ ruby -e 'if "foo\nbar" =~ /^[0-9a-z ]+$/i then puts "yes" else puts "no" end'
yes
EDIT: this is documented behavior for Ruby. What other languages call multiline mode is the default; you're supposed to use \A and \Z instead. They do have an `/m` but it only affects the interpretation of `.`https://docs.ruby-lang.org/en/master/Regexp.html#class-Regex...
Re: The dangers of single line regular expressions
#7Alternatively, don't validate and then use the original. Instead, pull out the acceptable input and use that. Even better, compare that to the original and fail validation if they're not identical, but that requires maintaining a higher level of paranoia than may be reasonable to expect.
Parse don't validate https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va...
Re: The dangers of single line regular expressions
#8In my experience `$` does reliably mean end of string for regular expressions, unless you specifically ask for "multiline" mode. Ruby seems to be in multiline mode all the time? $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foobar") else "no"' yes $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\nbar") else "no"' no $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\…
I think the simplest fix would be to use "\Z" rather than "$", which means "match end of input" rather than "end of line." This is also Perl-compatible. So weird that the "$" default meaning is different in Ruby.
I guess one could argue that Ruby's way is better since "$" has a fixed meaning, rather than being context-dependent.
> Ruby seems to be in multiline mode all the time?
Ruby does have a "/m" for multiline mode, but it just makes "." match newline, rather than changing the meaning of "$", it seems.
[1] https://ruby-doc.org/3.2.2/Regexp.html#class-Regexp-label-An...
Re: The dangers of single line regular expressions
#9I think it is a surprise that a partial match return true. But I guess this is why Python has so many ways of matching a pattern against a string (match, find, findall, I think - they are hard to remember)
Re: The dangers of single line regular expressions
#10In my experience `$` does reliably mean end of string for regular expressions, unless you specifically ask for "multiline" mode. Ruby seems to be in multiline mode all the time? $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foobar") else "no"' yes $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\nbar") else "no"' no $ python -c 'import re; print "yes" if re.match(r"^[a-z ]+$", "foo\…
Yeah, my takeaway from this was more "the dangers of Ruby" rather than "the dangers of single line regular expressions" (: I think the simplest fix would be to use "\Z" rather than "$", which means "match end of input" rather than "end of line." This is also Perl-compatible. So weird that the "$" default meaning is different in Ruby. I guess one could argue that Ruby's way is better since "$" has a fixed meaning, rat…