Skip to content
This repository

Convert lack of value to an empty string, not nil. #398

Closed
wants to merge 2 commits into from

6 participants

Egor Homakov Konstantin Haase Christian Neukirchen Steve Klabnik Don't Add Me To Your Organization a.k.a The Travis Bot James Tucker
Egor Homakov

Pros:
first - if we send "?admin" query then we are able to make conditions like this:

if params[:admin]
 ...
end

w/ nil we needed to check existance of key using has_key? and that is not nice.

second - we fix some CVE, known and possibly unknown.

Cons:
I don't see anything bad. Seems @tenderlove @steveklabnik don't see either.

Egor Homakov

also slight fix
next unless k || v
weird string, it will never happen. next if p.empty? above will skip iteration if string is empty but if string is not empty k will have some value thus that line is pointless

Konstantin Haase
Collaborator
rkh commented June 04, 2012

It would be really cool if you could provide tests with patches. Eases the process a lot.

Egor Homakov

@rkh sure but why to add tests if patch is not accepted yet?
I ask here about acceptance of the change and if you are ready to merge I provide anything.

Konstantin Haase
Collaborator
rkh commented June 05, 2012

Right, no, that's two different discussions, really. I see you wanna start a discussion first. A similar question would be: Why write an initial patch if the feature wasn't accepted yet.

Konstantin Haase rkh closed this June 05, 2012
Konstantin Haase rkh reopened this June 05, 2012
Egor Homakov

@rkh haha yes :) Sorry, if you haven't noticed, but discussion was kinda started https://twitter.com/steveklabnik/status/208993016134897664 https://twitter.com/tenderlove/status/208991607570182144
Writing the patch is easier than describing how it should work here, this is why. Could you describe why you are against of it?

Konstantin Haase
Collaborator
rkh commented June 05, 2012

Right. You have a link to the CVE?

Konstantin Haase
Collaborator
rkh commented June 05, 2012

Thanks.

Christian Neukirchen
Owner

I disagree. IMO, ?admin should just be accessible with QUERY_STRING, and not result in parameters at all.

But given how it is now, we should be able to differ "foo", "foo=" and "foo=&foo=".

Egor Homakov

@chneukirchen removing from parameters at all definitely not a way to go
why should we differ foo and foo= - we never need nil values and empty string is more comfortable default for developer. GET params are always must be k=v. just "k" is a bug in params and IMO to handle it we should turn it into "k="
also we never differ "foo=&foo=" do we?

Christian Neukirchen
Owner

There is a big semantic difference between ?foo (which is from an ISINDEX document) and ?foo= (which is an empty field in a form). And we differ on foo=&foo= which is ["", ""].

Steve Klabnik

(which is an empty field in a form)

This is not necessarily true. Neither is your assertion about what ?foo means. It is technically free-form, though key=value is often used to indicate key/value pairs. See RFC 3986 Sec 3.4 for more.

Christian Neukirchen
Owner
Steve Klabnik

Do you know of any case where FORMs are sent without =?

I meant the opposite; just because it's a key value doesn't mean that it was generated by a form.

Christian Neukirchen
Owner

It doesn't have to come from a form, but if you possibly send foo= bar, you'll never send just foo, you send foo=. Thus they should be different.

Steve Klabnik

You don't know that.

Christian Neukirchen
Owner

You also don't know that foo= is supposed to mean the same as foo.

Egor Homakov

@chneukirchen leaving it as is is not good, you was agreed in first post, right?
two options:
1. do not include keys w/o value, ?foo will not create params[:foo] at all.
2. create something different from nil, obviously empty string.
if both don't suit let's close it?

Christian Neukirchen
Owner

I think it should have been different in first place, but now we got to keep it as it is. Note its the same as in cgi.rb:

% irb -r cgi

CGI.parse("foo")
=> {"foo"=>[]}
CGI.parse("foo=")
=> {"foo"=>[""]}

Don't Add Me To Your Organization a.k.a The Travis Bot

This pull request passes (merged 1571308 into edc8b92).

James Tucker
Owner

I'll review this again ASAP. I'm concerned that we've gone back and forward over this code for security reasons plenty of times in the past, and the solution doesn't seem to be "interpret the parameters differently", the solution is "write your application code safely".

The last change in this area was made to ensure that parameters round-trip correctly through our existing encoders/decoders. At minimum this commit breaks that.

Whilst I'm considering that we should move away from CGI as a baseline for Rack 2, I'm not so sure that it's the right thing to do today, with Rack 1.x. CGI compliments HTTP (and other RFCs) to provide a more precise set of specifications, although still far from perfect (and far from up to date), the IDB in HTTP (and other RFCs) make all of this very complicated for the wider expanse of users we have.

Please try to remember that our users are not just using Rails/Sinatra on Unicorn/Puma/Mongrel/Thin.

Egor Homakov

@raggi

"interpret the parameters differently", the solution is "write your application code safely".

telling "write code safely" sounds funny to me. is it your only advice? :)

At minimum this commit breaks that

Really "breaks" or just requires some fixes? :)

James Tucker
Owner

References:

6127c81

5c00dd6

c9b4159

There are a few more, many of which were introduced / changed by Josh in 2009.

My largest concern with this is code the presently relies upon having a nil value in these cases. In the rails world, most people will be using blank? or present?, but in the rest of the ruby world, many folks will be using plain conditionals. Due to this I'm hesitant to introduce this any earlier than 1.5, if at all. It's also possible that adding another parse method with these kinds of semantics could be more safe, and Rails could migrate to using that instead.

Egor Homakov

BTW I can close this (marked with milestone?)
Problem was a security concern about find_by_*(nil). But eventually we found a way to send nil with JSON and XML too. Seems I have changed my mind and started to think ''x&y' are both nils. :) Up to you

James Tucker raggi closed this April 21, 2013
Egor Homakov homakov deleted the branch April 22, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
4  lib/rack/utils.rb
@@ -69,7 +69,8 @@ def parse_query(qs, d = nil)
69 69
       (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
70 70
         next if p.empty?
71 71
         k, v = p.split('=', 2).map { |x| unescape(x) }
72  
-        next unless k || v
  72
+        v = '' if v.nil?
  73
+        next unless k
73 74
 
74 75
         if cur = params[k]
75 76
           if cur.class == Array
@@ -102,6 +103,7 @@ def parse_nested_query(qs, d = nil)
102 103
     def normalize_params(params, name, v = nil)
103 104
       name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
104 105
       k = $1 || ''
  106
+      v = '' if v.nil?
105 107
       after = $' || ''
106 108
 
107 109
       return if k.empty?
6  test/spec_request.rb
@@ -118,11 +118,11 @@
118 118
   end
119 119
 
120 120
   should "parse the query string" do
121  
-    req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
  121
+    req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla&empty"))
122 122
     req.query_string.should.equal "foo=bar&quux=bla"
123  
-    req.GET.should.equal "foo" => "bar", "quux" => "bla"
  123
+    req.GET.should.equal "foo" => "bar", "quux" => "bla", "empty" => ""
124 124
     req.POST.should.be.empty
125  
-    req.params.should.equal "foo" => "bar", "quux" => "bla"
  125
+    req.params.should.equal "foo" => "bar", "quux" => "bla", "empty" => ""
126 126
   end
127 127
 
128 128
   should "limit the keys from the GET query string" do
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.