ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: prijutme4ty@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:71536] [Ruby trunk - Feature #10984] Hash#contain? to check whether hash contains other hash
Date: Wed, 18 Nov 2015 00:59:09 +0000	[thread overview]
Message-ID: <redmine.journal-54916.20151118005908.3a86eaa9d2ba2f3a@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-10984.20150319140059@ruby-lang.org

Issue #10984 has been updated by Ilya Vorontsov.


I've missed absence of `<=>` first. Yes, you are right. And it can slightly reduce damage.

But anyway it doesn't resolve issues with misinterpretation of comparison negation. My qsort function is just the one problem which lie on surface. There are lots `if (a < b) ...; else ...` constructions in lots of codebases.
I'm sure that such behaviour will lead to tons of subtle bugs. 

Also It's highly probable that some libraries will be subjected to malicious inputs which will cause infinite recursion bombs or other threats. Here I've slightly changed qsort code using `#reject` instead of `#select`. Not a very natural code but it's still correct:

```ruby
def qsort(arr)
  return arr  if arr.size <= 1
  pivot = arr[arr.length / 2]
  left = arr.reject{|el| el >= pivot }
  right = arr.reject{|el| el <= pivot }
  central = arr.select{|el| el == pivot }
  qsort(left) + central + qsort(right)
end
```

This code will not reduce size as in my previous example but contrariwise will expand array size and break asymptotical estimations of CPU time.

```ruby
qsort( [{}, {a:1,b:2}, {c:3}, {a:1}, {b:2}] )
# => [{}, {:b=>2}, {:a=>1}, {:b=>2}, {:a=>1, :b=>2}, {:c=>3}, {:b=>2}, {:a=>1}, {:b=>2}, {:a=>1, :b=>2}]
```

Look at expansion rate.

```ruby
qsort( 10.times.map{|i| {i => i} } ).size # => 1023
qsort( 20.times.map{|i| {i => i} } ).size # => 1048575
qsort( 25.times.map{|i| {i => i} } ).size # => 33554431
```

The last array of 25 single-element hashes is sorted in a minute or so. It can easily hang server.

Ok, I specially wrote code subjected to this attack. But in a large codebase of ruby community there would be places which have similar problems (which are not problems for totally ordered sets like numbers). It can be hard to find and exploit it, but if you did - you have broken the server. Just imagine that some code which earlies just raised an exception due to bad input now ruins your application.

----------------------------------------
Feature #10984: Hash#contain? to check whether hash contains other hash
https://bugs.ruby-lang.org/issues/10984#change-54916

* Author: Olivier Lacan
* Status: Closed
* Priority: Normal
* Assignee: Akira Tanaka
----------------------------------------
Comparing hashes seems like a common practice but there currently isn't a method to ask a 
hash instance whether it includes another hash instance.

The most intuitive method to reach for would be `Hash#include?` but it is in fact an alias to `Hash#has_key?`

What I'm looking for can be achieved with:

~~~
class Hash
  def contain?(other)
    self.merge(other) == self
  end
end
~~~

Here's a simple demo of `#contain?` in use:

~~~
{ a: true, b: false }.contain?({ a: true})
# => true

{ a: true, b: false }.contain?({ b: false})
# => true

{ a: true, b: false }.contain?({ a: false})
# => false

{ a: true, b: false }.contain?({ c: true})
# => false
~~~

One important note is that this method is *not checking for nested hash matches*.
This may need to be addressed when the parameters include a nested hash perhaps.

Thanks to Terence Lee's help, nobu created a patch for this feature last year. 
I've only modified the name of the method from [his original patch](https://gist.github.com/nobu/dfe8ba14a48fc949f2ed) and attached it to this issue.

---Files--------------------------------
Hash#contain_.patch (2.22 KB)


-- 
https://bugs.ruby-lang.org/

  parent reply	other threads:[~2015-11-18  0:28 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-10984.20150319140059@ruby-lang.org>
2015-03-19 14:01 ` [ruby-core:68561] [Ruby trunk - Feature #10984] [Open] Hash#contain? to check whether hash contains other hash hi
2015-03-19 14:11 ` [ruby-core:68562] [Ruby trunk - Feature #10984] " sferik
2015-03-19 14:20 ` [ruby-core:68563] " hi
2015-03-21 23:45 ` [ruby-core:68595] " shevegen
2015-08-18  4:30 ` [ruby-core:70444] " hi
2015-11-03 23:38 ` [ruby-core:71321] " hi
2015-11-04  3:39   ` [ruby-core:71328] " Юрий Соколов
2015-11-09  8:56 ` [ruby-core:71407] " matz
2015-11-09  8:57 ` [ruby-core:71408] " ko1
2015-11-09 15:06 ` [ruby-core:71419] " hi
2015-11-10  3:30 ` [ruby-core:71426] " nobu
2015-11-10  3:45 ` [ruby-core:71427] " akr
2015-11-11  5:33 ` [ruby-core:71440] " akr
2015-11-17 23:13 ` [ruby-core:71529] " prijutme4ty
2015-11-17 23:54 ` [ruby-core:71534] " hi
2015-11-18  0:59 ` prijutme4ty [this message]
2015-11-19  1:38 ` [ruby-core:71569] [Ruby trunk - Bug " prijutme4ty
2015-11-19  8:57 ` [ruby-core:71580] " nobu
2015-11-20 15:34 ` [ruby-core:71609] " from-ruby-lang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-54916.20151118005908.3a86eaa9d2ba2f3a@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).