sqreen 1.10.3 → 1.10.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sqreen/instrumentation.rb +61 -4
- data/lib/sqreen/rules_signature.rb +16 -2
- data/lib/sqreen/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdd2b054367e611564274927940b2cbc1f7d52c160b6288079a839da5a07c73a
|
4
|
+
data.tar.gz: 163fa3ce8ae72fe25635c1943eea48d00e5f54b6dfd222f66051ce2032f5763d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b142290e1c3f3f20d9a5a37da34c906f8ad3f3da4328d16f9354a9ba15bec6e0f9997eeb9837b6584fb6bf0e58f0118b2b38ac2c58641a2df376131373607b2
|
7
|
+
data.tar.gz: 2f8e8d35f50b9f4f1ef79fa7a7c695b3e816be16c422a65b21e55649991ecbd20a3f2781b891533af107e4027615f62368d609545e6a258e02b397511e0b910b
|
@@ -176,10 +176,29 @@ module Sqreen
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
+
def self.guard_multi_call(instance, method, original_method, args, block)
|
180
|
+
@sqreen_multi_instr ||= nil
|
181
|
+
key = [method]
|
182
|
+
Instrumentation.guard_call(nil, :guard_multi_call) do
|
183
|
+
args.each{|e| key.push(e.object_id)}
|
184
|
+
end
|
185
|
+
if key && @sqreen_multi_instr && @sqreen_multi_instr[instance.object_id].member?(key)
|
186
|
+
return instance.send(original_method, *args, &block)
|
187
|
+
end
|
188
|
+
@sqreen_multi_instr ||= Hash.new {|h, k| h[k]=Set.new } # TODO this should probably be a thread local
|
189
|
+
@sqreen_multi_instr[instance.object_id].add(key)
|
190
|
+
r = yield
|
191
|
+
return r
|
192
|
+
ensure
|
193
|
+
if @sqreen_multi_instr && @sqreen_multi_instr[instance.object_id] && @sqreen_multi_instr[instance.object_id].delete(key).empty?
|
194
|
+
@sqreen_multi_instr.delete(instance.object_id)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
179
198
|
def self.guard_call(method, retval)
|
180
199
|
@sqreen_in_instr ||= nil
|
181
200
|
return retval if @sqreen_in_instr && @sqreen_in_instr.member?(method)
|
182
|
-
@sqreen_in_instr ||= Set.new
|
201
|
+
@sqreen_in_instr ||= Set.new # TODO this should probably be a thread local
|
183
202
|
@sqreen_in_instr.add(method)
|
184
203
|
r = yield
|
185
204
|
@sqreen_in_instr.delete(method)
|
@@ -197,6 +216,7 @@ module Sqreen
|
|
197
216
|
end
|
198
217
|
return send(original_meth, *args, &block)
|
199
218
|
end
|
219
|
+
Instrumentation.guard_multi_call(self, meth, original_meth, args, block) do
|
200
220
|
Sqreen.stats.callbacks_calls += 1
|
201
221
|
|
202
222
|
skip = false
|
@@ -271,6 +291,7 @@ module Sqreen
|
|
271
291
|
result
|
272
292
|
end
|
273
293
|
end
|
294
|
+
end
|
274
295
|
end
|
275
296
|
|
276
297
|
def override_class_method(klass, meth)
|
@@ -325,8 +346,8 @@ module Sqreen
|
|
325
346
|
end
|
326
347
|
end
|
327
348
|
|
328
|
-
def get_saved_method_name(meth)
|
329
|
-
"#{meth}_not_modified".to_sym
|
349
|
+
def get_saved_method_name(meth, suffix=nil)
|
350
|
+
"#{meth}_sq#{suffix}_not_modified".to_sym
|
330
351
|
end
|
331
352
|
|
332
353
|
def override_instance_method(klass_name, meth)
|
@@ -403,6 +424,30 @@ module Sqreen
|
|
403
424
|
is_instance_method?(obj, method)
|
404
425
|
end
|
405
426
|
|
427
|
+
# Override a singleton method on an instance
|
428
|
+
def override_singleton_method(instance, klass_name, meth)
|
429
|
+
saved_meth_name = get_saved_method_name(meth, 'singleton')
|
430
|
+
if instance.respond_to?(saved_meth_name, true)
|
431
|
+
Sqreen.log.debug { "#{saved_meth_name} found #{instance.class}##{instance.object_id} already instrumented" }
|
432
|
+
return nil
|
433
|
+
elsif instance.frozen?
|
434
|
+
Sqreen.log.debug { "#{instance.class}##{instance.object_id} is frozen, not reinstrumenting" }
|
435
|
+
return nil
|
436
|
+
end
|
437
|
+
raise Sqreen::NotImplementedYet, "#{instance.inspect} doesn't respond to define_singleton_method" unless instance.respond_to?(:define_singleton_method)
|
438
|
+
p = Instrumentation.define_callback_method(meth, saved_meth_name,
|
439
|
+
klass_name)
|
440
|
+
instance.define_singleton_method(saved_meth_name, instance.method(meth))
|
441
|
+
instance.define_singleton_method(meth, p)
|
442
|
+
# Hide saved method (its only available in this syntax)
|
443
|
+
eval <<-RUBY, binding, __FILE__, __LINE__ + 1
|
444
|
+
class << instance
|
445
|
+
private :#{saved_meth_name}
|
446
|
+
end
|
447
|
+
saved_meth_name
|
448
|
+
RUBY
|
449
|
+
end
|
450
|
+
|
406
451
|
def add_callback(cb)
|
407
452
|
@@override_semaphore.synchronize do
|
408
453
|
klass = cb.klass
|
@@ -427,7 +472,7 @@ module Sqreen
|
|
427
472
|
# - method_missing
|
428
473
|
# ...
|
429
474
|
#
|
430
|
-
msg = "#{cb} is neither
|
475
|
+
msg = "#{cb} is neither class or instance"
|
431
476
|
raise Sqreen::NotImplementedYet, msg
|
432
477
|
end
|
433
478
|
|
@@ -436,6 +481,18 @@ module Sqreen
|
|
436
481
|
Sqreen.log.debug "#{key} was already overriden"
|
437
482
|
end
|
438
483
|
|
484
|
+
if klass != Object && klass != Kernel && !Sqreen.features['instrument_all_instances'] && !defined?(::JRUBY_VERSION)
|
485
|
+
insts = 0
|
486
|
+
ObjectSpace.each_object(klass) do |e|
|
487
|
+
next if e.is_a?(Class) || e.is_a?(Module)
|
488
|
+
next unless e.singleton_methods.include?(method.to_sym)
|
489
|
+
insts += 1 if override_singleton_method(e, klass, method)
|
490
|
+
end
|
491
|
+
if insts > 0
|
492
|
+
Sqreen.log.debug { "Reinstrumented #{insts} instances of #{klass}" }
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
439
496
|
@@registered_callbacks.add(cb)
|
440
497
|
@@instrumented_pid = Process.pid
|
441
498
|
end
|
@@ -7,6 +7,16 @@ require 'set'
|
|
7
7
|
require 'openssl'
|
8
8
|
require 'base64'
|
9
9
|
require 'json'
|
10
|
+
if defined?(::JRUBY_VERSION)
|
11
|
+
OJ_LOADED = false
|
12
|
+
else
|
13
|
+
begin
|
14
|
+
require "oj"
|
15
|
+
OJ_LOADED = true
|
16
|
+
rescue LoadError
|
17
|
+
OJ_LOADED = false
|
18
|
+
end
|
19
|
+
end
|
10
20
|
|
11
21
|
## Rules signature
|
12
22
|
module Sqreen
|
@@ -25,7 +35,7 @@ module Sqreen
|
|
25
35
|
|
26
36
|
# Normalize and verify a rule
|
27
37
|
class SqreenSignedVerifier
|
28
|
-
REQUIRED_SIGNED_KEYS = %w
|
38
|
+
REQUIRED_SIGNED_KEYS = %w[hookpoint name callbacks conditions].freeze
|
29
39
|
SIGNATURE_KEY = 'signature'.freeze
|
30
40
|
SIGNATURE_VALUE_KEY = 'value'.freeze
|
31
41
|
SIGNED_KEYS_KEY = 'keys'.freeze
|
@@ -42,12 +52,14 @@ module Sqreen
|
|
42
52
|
attr_accessor :pub_key
|
43
53
|
attr_accessor :required_signed_keys
|
44
54
|
attr_accessor :digest
|
55
|
+
attr_accessor :use_oj
|
45
56
|
|
46
57
|
def initialize(required_keys = REQUIRED_SIGNED_KEYS,
|
47
58
|
public_key = PUBLIC_KEY,
|
48
|
-
digest = OpenSSL::Digest::SHA512.new)
|
59
|
+
digest = OpenSSL::Digest::SHA512.new, use_oj_gem = nil)
|
49
60
|
@required_signed_keys = required_keys
|
50
61
|
@signature_verifier = SignatureVerifier.new(public_key, digest)
|
62
|
+
@use_oj = use_oj_gem.nil? ? OJ_LOADED : use_oj_gem
|
51
63
|
end
|
52
64
|
|
53
65
|
def normalize_val(val, level)
|
@@ -62,6 +74,7 @@ module Sqreen
|
|
62
74
|
end
|
63
75
|
"[#{ary.join(',')}]"
|
64
76
|
when String, Integer
|
77
|
+
return Oj.dump(val, :mode => :compat, :escape_mode => :json) if use_oj
|
65
78
|
begin
|
66
79
|
JSON.dump(val)
|
67
80
|
rescue JSON::GeneratorError
|
@@ -76,6 +89,7 @@ module Sqreen
|
|
76
89
|
def normalize_key(key)
|
77
90
|
case key
|
78
91
|
when String, Integer
|
92
|
+
return Oj.dump(key, :mode => :compat, :escape_mode => :json) if use_oj
|
79
93
|
begin
|
80
94
|
JSON.dump(key)
|
81
95
|
rescue JSON::GeneratorError
|
data/lib/sqreen/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqreen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.10.
|
4
|
+
version: 1.10.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sqreen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: execjs
|