sqreen 1.10.3 → 1.10.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|