sql-maker 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 32d150cb48d1dafd939ac1562fc6e7a31195172d
4
- data.tar.gz: 749f497d5f5a1f5d38a1f1855e575725b862bf9a
3
+ metadata.gz: df6b66323d8c864915eacfa06aecea6273e58c46
4
+ data.tar.gz: 307efe4066f6b8ab303fe749ea80ae8022737325
5
5
  SHA512:
6
- metadata.gz: a474871843140b6871e998e583bfe4222a89dc43db85f4a121379438eaf80bb648a36749166f91da4fffa69e8eff9d103f278a39860bf78960eb06e7916c2405
7
- data.tar.gz: 994cf90b1c734b301f7fb4c09bdedfe55a8c00bb5ec38530874be625c3f939d7f94c33cea071dae1b6062868d6e4dbcf21decd932978f86c10b8456e1ea517a3
6
+ metadata.gz: 26c0a612e3bb5a35709ba269a2e775a10923cc0f628ff333d9226a2183947cc7bf034bd24b974271078150eb84fa18a6b29b9f48a4b194048d7628db1c0eac39
7
+ data.tar.gz: aadebe81d0678883500fc8dae3f2a66b7e799e7cebf23ef2a58f70e5f2be1de80dfb2cef5c850230f540c5d2a2fa3bd9bca4afc24762fa5d5e33667dbd3787dd
@@ -1,3 +1,9 @@
1
+ ## 0.0.4 (2014/09/14)
2
+
3
+ Fixes:
4
+
5
+ * Fixed strict mode for insert/update (thanks to memememomo)
6
+
1
7
  ## 0.0.3 (2014/06/21)
2
8
 
3
9
  Fixes:
data/README.md CHANGED
@@ -42,6 +42,44 @@ builder.add_select(sql_raw('COUNT(*)')).add_from('books').as_sql
42
42
 
43
43
  Please see the [doc](./doc) directory.
44
44
 
45
+ ## The JSON SQL Injection Vulnerability
46
+
47
+ Both perl and ruby verion of SQL::Maker has a JSON SQL Injection Vulnerability if not used in `strict` mode.
48
+
49
+ Therefore, I strongly recommend to use SQL::Maker in `strict` mode.
50
+ You can turn on the `strict` mode by passing `:strict => true` as:
51
+
52
+ ```ruby
53
+ SQL::Maker.new(...., :strict => true)
54
+ SQL::Maker::Select.new(...., :strict => true)
55
+ ```
56
+
57
+ In strict mode, array or hash conditions are not accepted anymore. A sample usage snippet is shown in below:
58
+
59
+ ```ruby
60
+ require 'sql-maker'
61
+ include SQL::Maker::Helper # adds SQL::QueryMaker functions such as sql_le, etc
62
+
63
+ builder = SQL::Maker::Select.new(:strict => true)
64
+
65
+ builder.select('user', ['*'], {:name => json['name']})
66
+ #=> SELECT * FROM `user` WHERE `name` = ?
67
+
68
+ builder.select('user', ['*'], {:name => ['foo', 'bar']})
69
+ #=> SQL::Maker::Error! Will not generate SELECT * FROM `name` IN (?, ?) any more
70
+
71
+ builder.select('user', ['*'], {:name => sql_in(['foo', 'bar'])})
72
+ #=> SELECT * FROM `user` WHERE `name` IN (?, ?)
73
+
74
+ builder.select('fruit', ['*'], {:price => sql_le(json['max_price'])})
75
+ #=> SELECT * FROM `fruit` WHERE `price` <= ?
76
+ ```
77
+
78
+ See following articles for more details (perl version)
79
+
80
+ * http://blog.kazuhooku.com/2014/07/the-json-sql-injection-vulnerability.html (English)
81
+ * http://developers.mobage.jp/blog/2014/7/3/jsonsql-injection (Japanese)
82
+
45
83
  ## ChangeLog
46
84
 
47
85
  See [CHANGELOG.md](CHANGELOG.md) for details.
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require "bundler/gem_tasks"
3
3
  require 'rspec/core'
4
4
  require 'rspec/core/rake_task'
5
5
  RSpec::Core::RakeTask.new(:spec) do |spec|
6
- spec.pattern = FileList['spec/**/*_spec.rb']
6
+ spec.pattern = 'spec/**{,/*/**}/*_spec.rb'
7
7
  end
8
8
  task :default => :spec
9
9
 
@@ -5,4 +5,4 @@
5
5
  * [sql/maker/condition.md](./sql/maker/condition.md)
6
6
  * [sql/maker/helper.md](./sql/maker/helper.md)
7
7
  * [sql/maker/select_set.md](./sql/maker/select_set.md)
8
- * [sql/queyr_maker.md](./sql/maker.md)
8
+ * [sql/query_maker.md](./sql/query_maker.md)
@@ -84,11 +84,12 @@ class SQL::Maker
84
84
  columns += [val.as_sql(nil, Proc.new {|e| self._quote(e) })]
85
85
  bind_columns += val.bind
86
86
  else
87
- croak("cannot pass in an unblessed ref as an argument in strict mode") if self.strict
88
- if val.is_a?(Hash)
89
- # builder.insert(:foo => { :created_on => ["NOW()"] })
90
- columns += [val]
91
- elsif val.is_a?(Array)
87
+ if val.is_a?(Array) && self.strict
88
+ croak("cannot pass in an unblessed ref as an argument in strict mode")
89
+ end
90
+
91
+ if val.is_a?(Array)
92
+ # builder.insert( :foo => { :created_on => ["NOW()"] })
92
93
  # builder.insert( :foo => [ 'UNIX_TIMESTAMP(?)', '2011-04-12 00:34:12' ] )
93
94
  stmt, sub_bind = [val.first, val[1..-1]]
94
95
  columns += [stmt]
@@ -181,14 +182,13 @@ class SQL::Maker
181
182
  columns += ["#{quoted_col} = " + val.as_sql(nil, Proc.new {|label| self._quote(label) })]
182
183
  bind_columns += val.bind
183
184
  else
184
- if self.strict
185
+ if val.is_a?(Array) && self.strict
185
186
  croak("cannot pass in an unblessed ref as an argument in strict mode")
186
- if val.is_a?(Hash)
187
- # builder.update(:foo => { :created_on => \"NOW()" })
188
- # columns += ["quoted_col = " + $val
189
- end
190
- elsif val.is_a?(Array)
191
- # builder.update( :foo => \[ 'VALUES(foo) + ?', 10 ] )
187
+ end
188
+
189
+ if val.is_a?(Array)
190
+ # builder.update( :foo => [ 'NOW()' ] )
191
+ # builder.update( :foo => [ 'VALUES(foo) + ?', 10 ] )
192
192
  stmt, sub_bind = [val.first, val[1..-1]]
193
193
  columns += ["#{quoted_col} = " + stmt]
194
194
  bind_columns += sub_bind
@@ -44,7 +44,7 @@ class SQL::Maker::Condition
44
44
  if val.is_a?(SQL::QueryMaker)
45
45
  return [val.as_sql(col, self.method(:_quote)), val.bind]
46
46
  elsif self.strict
47
- croak("can pass only SQL::QueryMaker as an argument in strict mode")
47
+ croak("Condition#add: can pass only SQL::QueryMaker object as an argument in strict mode")
48
48
  end
49
49
 
50
50
  if val.is_a?(Array)
@@ -57,18 +57,17 @@ class SQL::Maker::Condition
57
57
  end
58
58
  elsif val.is_a?(Hash)
59
59
  op, v = val.each.first
60
- op = op.upcase.to_s
60
+ op = op.to_s.upcase
61
61
  if ( op == 'AND' || op == 'OR' ) && v.is_a?(Array)
62
- # {'foo'=>[{'>' => 'bar'},{'<' => 'baz'}]} => (`foo` > ?) OR (`foo` < ?)
62
+ # {'foo'=>{'or' => [{'>' => 'bar'},{'<' => 'baz'}]}} => (`foo` > ?) OR (`foo` < ?)
63
63
  return self._make_or_term(col, op, v)
64
64
  elsif ( op == 'IN' || op == 'NOT IN' )
65
+ # {'foo'=>{'in' => ['bar','baz']}} => `foo` IN (?, ?)
65
66
  return self._make_in_term(col, op, v)
66
67
  elsif ( op == 'BETWEEN' ) && v.is_a?(Array)
67
- croak("USAGE: make_term(foo => {BETWEEN => [a, b]})") if v.size != 2
68
+ croak("USAGE: add(foo => {BETWEEN => [a, b]})") if v.size != 2
68
69
  return [self._quote(col) + " BETWEEN ? AND ?", v]
69
70
  else
70
- # make_term(foo => { '<' => \"DATE_SUB(NOW(), INTERVAL 3 DAY)"}) => 'foo < DATE_SUB(NOW(), INTERVAL 3 DAY)'
71
- # return [self._quote(col) + " op " + v, []]
72
71
  # make_term(foo => { '<' => 3 }) => foo < 3
73
72
  return [self._quote(col) + " #{op} ?", [v]]
74
73
  end
@@ -2,6 +2,8 @@ require_relative '../spec_helper'
2
2
  require 'sql/maker'
3
3
 
4
4
  describe 'SQL::Maker' do
5
+ include SQL::Maker::Helper
6
+
5
7
  let(:maker) do
6
8
  SQL::Maker.new(
7
9
  :driver => 'SQLite',
@@ -13,6 +15,7 @@ describe 'SQL::Maker' do
13
15
 
14
16
  it "maker.new_condition" do
15
17
  expect { maker.new_condition.add(:foo => [1]) }.to raise_error(SQL::Maker::Error)
18
+ expect { maker.new_condition.add(:foo => {'!=' => ''}) }.to raise_error(SQL::Maker::Error)
16
19
  end
17
20
 
18
21
  it "select.new_condition" do
@@ -25,21 +28,37 @@ describe 'SQL::Maker' do
25
28
  expect { maker.select("user", ['*'], { :name => ["John", "Tom" ]}) }.to raise_error(SQL::Maker::Error)
26
29
  end
27
30
 
28
- it "maker.insert" do
29
- expect { maker.insert(
30
- :user, { :name => "John", :created_on => "datetime(now)" }
31
- ) }.to raise_error(SQL::Maker::Error)
31
+ context "maker.insert" do
32
+ it "raise error by strict mode" do
33
+ expect { maker.insert(
34
+ :user, { :name => "John", :created_on => ["datetime(now)"] }
35
+ ) }.to raise_error(SQL::Maker::Error)
36
+ end
37
+
38
+ it "using term" do
39
+ sql, binds = maker.insert(:user, { :name => "John", :created_on => sql_raw("datetime(now)") })
40
+ expect(sql).to be == %Q{INSERT INTO "user"\n("name", "created_on")\nVALUES (?, datetime(now))}
41
+ expect(binds.join(',')).to be == 'John'
42
+ end
32
43
  end
33
44
 
34
45
  it "maker.delete" do
35
46
  expect { maker.delete(:user, { :name => ["John", "Tom"]}) }.to raise_error(SQL::Maker::Error)
36
47
  end
37
48
 
38
- it "maker.update where" do
39
- expect { maker.update(:user, {:name => "John"}, { :user_id => [1, 2] }) }.to raise_error(SQL::Maker::Error)
49
+ context "maker.update where" do
50
+ it "raise error by strict mode" do
51
+ expect { maker.update(:user, {:name => "John"}, { :user_id => [1, 2] }) }.to raise_error(SQL::Maker::Error)
52
+ end
53
+
54
+ it "using term" do
55
+ sql, binds = maker.update(:user, {:name => "John"}, { :user_id => sql_in([1, 2]) })
56
+ expect(sql).to be == %Q{UPDATE "user" SET "name" = ? WHERE ("user_id" IN (?,?))}
57
+ expect(binds.join(',')).to be == 'John,1,2'
58
+ end
40
59
  end
41
60
 
42
61
  it "maker.update set" do
43
- expect { maker.update(:user, {:name => "select *"}) }.to raise_error(SQL::Maker::Error)
62
+ expect { sql, bind = maker.update(:user, {:name => ["select *"]}) }.to raise_error(SQL::Maker::Error)
44
63
  end
45
64
  end
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "sql-maker"
7
- spec.version = "0.0.3"
7
+ spec.version = "0.0.4"
8
8
  spec.authors = ["Naotoshi Seo"]
9
9
  spec.email = ["sonots@gmail.com"]
10
10
  spec.summary = %q{SQL Builder for Ruby}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sql-maker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naotoshi Seo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-21 00:00:00.000000000 Z
11
+ date: 2014-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler