sqreen 1.11.0-java → 1.11.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sqreen.rb +0 -1
- data/lib/sqreen/callback_tree.rb +38 -20
- data/lib/sqreen/callbacks.rb +6 -4
- data/lib/sqreen/conditionable.rb +3 -3
- data/lib/sqreen/frameworks/generic.rb +38 -18
- data/lib/sqreen/frameworks/request_recorder.rb +0 -2
- data/lib/sqreen/instrumentation.rb +217 -160
- data/lib/sqreen/performance_notifications.rb +10 -36
- data/lib/sqreen/performance_notifications/log.rb +1 -2
- data/lib/sqreen/performance_notifications/log_performance.rb +1 -2
- data/lib/sqreen/performance_notifications/metrics.rb +1 -2
- data/lib/sqreen/performance_notifications/newrelic.rb +1 -2
- data/lib/sqreen/remote_command.rb +7 -7
- data/lib/sqreen/rule_callback.rb +4 -0
- data/lib/sqreen/rules.rb +2 -2
- data/lib/sqreen/rules_callbacks/binding_accessor_matcher.rb +7 -1
- data/lib/sqreen/rules_callbacks/binding_accessor_metrics.rb +3 -3
- data/lib/sqreen/rules_callbacks/blacklist_ips.rb +1 -1
- data/lib/sqreen/rules_callbacks/count_http_codes.rb +7 -6
- data/lib/sqreen/rules_callbacks/crawler_user_agent_matches.rb +1 -1
- data/lib/sqreen/rules_callbacks/crawler_user_agent_matches_metrics.rb +1 -1
- data/lib/sqreen/rules_callbacks/custom_error.rb +2 -5
- data/lib/sqreen/rules_callbacks/execjs.rb +76 -37
- data/lib/sqreen/rules_callbacks/headers_insert.rb +1 -1
- data/lib/sqreen/rules_callbacks/inspect_rule.rb +3 -3
- data/lib/sqreen/rules_callbacks/matcher_rule.rb +18 -17
- data/lib/sqreen/rules_callbacks/rails_parameters.rb +1 -1
- data/lib/sqreen/rules_callbacks/record_request_context.rb +9 -8
- data/lib/sqreen/rules_callbacks/reflected_xss.rb +40 -34
- data/lib/sqreen/rules_callbacks/regexp_rule.rb +13 -4
- data/lib/sqreen/rules_callbacks/shell_env.rb +2 -2
- data/lib/sqreen/rules_callbacks/url_matches.rb +1 -1
- data/lib/sqreen/rules_callbacks/user_agent_matches.rb +1 -1
- data/lib/sqreen/session.rb +1 -1
- data/lib/sqreen/shared_storage.rb +16 -12
- data/lib/sqreen/{stats.rb → shared_storage23.rb} +3 -11
- data/lib/sqreen/version.rb +1 -1
- metadata +4 -4
@@ -15,22 +15,13 @@ module Sqreen
|
|
15
15
|
#
|
16
16
|
module PerformanceNotifications
|
17
17
|
@subscriptions_all = {}
|
18
|
-
@subscriptions_regexp = {}
|
19
|
-
@subscriptions_val = Hash.new { |h, k| h[k] = [] }
|
20
18
|
@subscription_id = 0
|
21
19
|
class << self
|
22
20
|
# Subsribe to receive notificiations about an event
|
23
21
|
# returns a subscription indentitifcation
|
24
|
-
def subscribe(
|
22
|
+
def subscribe(&block)
|
25
23
|
id = (@subscription_id += 1)
|
26
|
-
|
27
|
-
when NilClass
|
28
|
-
@subscriptions_all[id] = block
|
29
|
-
when Regexp
|
30
|
-
@subscriptions_regexp[id] = [pattern, block]
|
31
|
-
else
|
32
|
-
@subscriptions_val[pattern].push([id, block])
|
33
|
-
end
|
24
|
+
@subscriptions_all[id] = block
|
34
25
|
id
|
35
26
|
end
|
36
27
|
|
@@ -44,22 +35,20 @@ module Sqreen
|
|
44
35
|
end
|
45
36
|
end
|
46
37
|
|
47
|
-
# Is there a subscriber
|
48
|
-
def listen_for?
|
49
|
-
|
50
|
-
return true if @subscriptions_val.key?(key)
|
51
|
-
@subscriptions_regexp.values.any? { |r| r.first.match(key) }
|
38
|
+
# Is there a subscriber
|
39
|
+
def listen_for?
|
40
|
+
!@subscriptions_all.empty?
|
52
41
|
end
|
53
42
|
|
54
43
|
# Instrument a call identified by key
|
55
44
|
def instrument(key, meta = {}, &block)
|
56
|
-
return yield unless listen_for?
|
45
|
+
return yield unless listen_for?
|
57
46
|
_instrument(key, meta, &block)
|
58
47
|
end
|
59
48
|
|
60
49
|
def notify(key, start, stop, meta = {})
|
61
|
-
return unless listen_for?
|
62
|
-
|
50
|
+
return unless listen_for?
|
51
|
+
notifiers.each do |callable|
|
63
52
|
callable.call(key, start, stop, meta)
|
64
53
|
end
|
65
54
|
end
|
@@ -67,33 +56,18 @@ module Sqreen
|
|
67
56
|
# Unsubscrube for a given subscription
|
68
57
|
def unsubscribe(subscription)
|
69
58
|
return unless @subscriptions_all.delete(subscription).nil?
|
70
|
-
return unless @subscriptions_regexp.delete(subscription).nil?
|
71
|
-
@subscriptions_val.delete_if do |_, v|
|
72
|
-
v.delete_if { |r| r.first == subscription }
|
73
|
-
v.empty?
|
74
|
-
end
|
75
59
|
end
|
76
60
|
|
77
61
|
# Unsubscribe from everything
|
78
62
|
# not threadsafe
|
79
63
|
def unsubscribe_all!
|
80
64
|
@subscriptions_all.clear
|
81
|
-
@subscriptions_regexp.clear
|
82
|
-
@subscriptions_val.clear
|
83
65
|
end
|
84
66
|
|
85
67
|
private
|
86
68
|
|
87
|
-
def
|
88
|
-
|
89
|
-
r.first.match(key) && r.last
|
90
|
-
end
|
91
|
-
reg.compact!
|
92
|
-
str = []
|
93
|
-
if @subscriptions_val.key?(key)
|
94
|
-
str = @subscriptions_val[key].map(&:last)
|
95
|
-
end
|
96
|
-
@subscriptions_all.values + str + reg
|
69
|
+
def notifiers
|
70
|
+
@subscriptions_all.values
|
97
71
|
end
|
98
72
|
|
99
73
|
if SQREEN_MONO_TIME
|
@@ -21,8 +21,7 @@ module Sqreen
|
|
21
21
|
def enable(facility = nil)
|
22
22
|
return unless @subid.nil?
|
23
23
|
@facility = facility
|
24
|
-
@subid = Sqreen::PerformanceNotifications.subscribe(
|
25
|
-
&method(:log))
|
24
|
+
@subid = Sqreen::PerformanceNotifications.subscribe(&method(:log))
|
26
25
|
end
|
27
26
|
|
28
27
|
def disable
|
@@ -55,8 +55,7 @@ module Sqreen
|
|
55
55
|
def enable(facility = nil)
|
56
56
|
return unless @subid.nil?
|
57
57
|
@facility = facility
|
58
|
-
@subid = Sqreen::PerformanceNotifications.subscribe(
|
59
|
-
&method(:log))
|
58
|
+
@subid = Sqreen::PerformanceNotifications.subscribe(&method(:log))
|
60
59
|
end
|
61
60
|
|
62
61
|
def disable
|
@@ -21,8 +21,7 @@ module Sqreen
|
|
21
21
|
metrics_engine.create_metric('name' => EVENT_CAT,
|
22
22
|
'period' => period,
|
23
23
|
'kind' => 'Average')
|
24
|
-
@subid = Sqreen::PerformanceNotifications.subscribe(
|
25
|
-
&method(:log))
|
24
|
+
@subid = Sqreen::PerformanceNotifications.subscribe(&method(:log))
|
26
25
|
end
|
27
26
|
|
28
27
|
def disable
|
@@ -76,8 +76,7 @@ module Sqreen
|
|
76
76
|
return unless level > 0
|
77
77
|
@level = level
|
78
78
|
Sqreen.log.debug('Enabling New Relic reporting')
|
79
|
-
@subid = Sqreen::PerformanceNotifications.subscribe(
|
80
|
-
&method(:log))
|
79
|
+
@subid = Sqreen::PerformanceNotifications.subscribe(&method(:log))
|
81
80
|
end
|
82
81
|
|
83
82
|
def disable
|
@@ -30,7 +30,7 @@ module Sqreen
|
|
30
30
|
def process(runner, context_infos = {})
|
31
31
|
failing = validate_command(runner)
|
32
32
|
return failing if failing
|
33
|
-
Sqreen.log.debug format('processing command %s', @name)
|
33
|
+
Sqreen.log.debug { format('processing command %s', @name) }
|
34
34
|
begin
|
35
35
|
output = runner.send(KNOWN_COMMANDS[@name], *@params, context_infos)
|
36
36
|
rescue => e
|
@@ -46,14 +46,14 @@ module Sqreen
|
|
46
46
|
return res_list unless commands
|
47
47
|
|
48
48
|
unless commands.is_a? Array
|
49
|
-
Sqreen.log.debug format('Wrong commands type %s', commands.class)
|
50
|
-
Sqreen.log.debug commands.inspect
|
49
|
+
Sqreen.log.debug { format('Wrong commands type %s', commands.class) }
|
50
|
+
Sqreen.log.debug { commands.inspect }
|
51
51
|
return res_list
|
52
52
|
end
|
53
53
|
commands.each do |cmd_json|
|
54
|
-
Sqreen.log.debug cmd_json
|
54
|
+
Sqreen.log.debug { cmd_json }
|
55
55
|
cmd = RemoteCommand.new(cmd_json)
|
56
|
-
Sqreen.log.debug cmd.inspect
|
56
|
+
Sqreen.log.debug { cmd.inspect }
|
57
57
|
uuid = cmd.uuid
|
58
58
|
res_list[uuid] = cmd.process(runner, context_infos)
|
59
59
|
end
|
@@ -71,12 +71,12 @@ module Sqreen
|
|
71
71
|
def validate_command(runner)
|
72
72
|
unless KNOWN_COMMANDS.include?(@name)
|
73
73
|
msg = format("unknown command name '%s'", @name)
|
74
|
-
Sqreen.log.debug msg
|
74
|
+
Sqreen.log.debug { msg }
|
75
75
|
return { :status => false, :reason => msg }
|
76
76
|
end
|
77
77
|
return nil if runner.respond_to?(KNOWN_COMMANDS[@name])
|
78
78
|
msg = format("not implemented '%s'", @name)
|
79
|
-
Sqreen.log.debug msg
|
79
|
+
Sqreen.log.debug { msg }
|
80
80
|
{ :status => false, :reason => msg }
|
81
81
|
end
|
82
82
|
|
data/lib/sqreen/rule_callback.rb
CHANGED
@@ -35,6 +35,7 @@ module Sqreen
|
|
35
35
|
@data = rule_hash[Attrs::DATA]
|
36
36
|
@rule = rule_hash
|
37
37
|
@payload_tpl = @rule[Attrs::PAYLOAD] || DEFAULT_PAYLOAD
|
38
|
+
@overtimeable = true
|
38
39
|
condition_callbacks(@rule[Attrs::CONDITIONS])
|
39
40
|
count_callback_calls(@rule[Attrs::CALL_COUNT_INTERVAL])
|
40
41
|
end
|
@@ -48,6 +49,8 @@ module Sqreen
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def whitelisted?
|
52
|
+
whitelisted = SharedStorage.get(:whitelisted)
|
53
|
+
return whitelisted unless whitelisted.nil?
|
51
54
|
framework && !framework.whitelisted_match.nil?
|
52
55
|
end
|
53
56
|
|
@@ -105,6 +108,7 @@ module Sqreen
|
|
105
108
|
end
|
106
109
|
|
107
110
|
def overtime!
|
111
|
+
return false unless @overtimeable
|
108
112
|
Sqreen.log.debug { "rulecb #{self} is overtime!" }
|
109
113
|
return true if framework.nil? || !framework.mark_request_overtime!
|
110
114
|
record_observation(
|
data/lib/sqreen/rules.rb
CHANGED
@@ -83,7 +83,7 @@ module Sqreen
|
|
83
83
|
end
|
84
84
|
|
85
85
|
if cb_class.nil?
|
86
|
-
Sqreen.log.debug "Cannot setup #{cbname.inspect} [#{rule_name}]"
|
86
|
+
Sqreen.log.debug { "Cannot setup #{cbname.inspect} [#{rule_name}]" }
|
87
87
|
return nil
|
88
88
|
end
|
89
89
|
|
@@ -110,7 +110,7 @@ module Sqreen
|
|
110
110
|
'exception' => e,
|
111
111
|
'rulespack_id' => rulespack_id,
|
112
112
|
'rule_name' => rule_name)
|
113
|
-
Sqreen.log.debug
|
113
|
+
Sqreen.log.debug { "Creating cb from rule #{rule_name} failed (#{e.inspect})" }
|
114
114
|
nil
|
115
115
|
end
|
116
116
|
|
@@ -47,7 +47,10 @@ module Sqreen
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def pre(inst,
|
50
|
+
def pre(inst, args, budget = nil, &_block)
|
51
|
+
unless budget.nil?
|
52
|
+
finish = budget + Sqreen::PerformanceNotifications.time.to_f
|
53
|
+
end
|
51
54
|
resol_cache = Hash.new do |hash, accessor|
|
52
55
|
hash[accessor] = accessor.resolve(binding, framework, inst, args)
|
53
56
|
end
|
@@ -58,6 +61,9 @@ module Sqreen
|
|
58
61
|
next unless val.respond_to?(:each)
|
59
62
|
next if val.respond_to?(:seek)
|
60
63
|
val.each do |v|
|
64
|
+
if !budget.nil? && Sqreen::PerformanceNotifications.time.to_f > finish
|
65
|
+
return nil
|
66
|
+
end
|
61
67
|
next if !v.is_a?(String) || (!matcher.min_size.nil? && v.size < matcher.min_size)
|
62
68
|
next if v.size > MAX_LENGTH
|
63
69
|
next if matcher.match(v).nil?
|
@@ -38,19 +38,19 @@ module Sqreen
|
|
38
38
|
@expr[FAILING_CB]
|
39
39
|
end
|
40
40
|
|
41
|
-
def pre(inst,
|
41
|
+
def pre(inst, args, _budget = nil, &_block)
|
42
42
|
return unless pre?
|
43
43
|
|
44
44
|
add_metrics(PRE_CB, inst, args)
|
45
45
|
end
|
46
46
|
|
47
|
-
def post(rv, inst,
|
47
|
+
def post(rv, inst, args, _budget = nil, &_block)
|
48
48
|
return unless post?
|
49
49
|
|
50
50
|
add_metrics(POST_CB, inst, args, rv)
|
51
51
|
end
|
52
52
|
|
53
|
-
def failing(exception, inst,
|
53
|
+
def failing(exception, inst, args, _budget = nil, &_block)
|
54
54
|
return unless failing?
|
55
55
|
|
56
56
|
add_metrics(FAILING_CB, inst, args, exception)
|
@@ -10,15 +10,16 @@ module Sqreen
|
|
10
10
|
# Save request context for handling further down
|
11
11
|
class CountHTTPCodes < RuleCB
|
12
12
|
METRIC_CATEGORY = 'http_code'.freeze
|
13
|
-
def
|
13
|
+
def initialize(*args)
|
14
|
+
super(*args)
|
15
|
+
@overtimeable = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def post(rv, _inst, _args, _budget = nil, &_block)
|
14
19
|
return unless rv.is_a?(Array) && !rv.empty?
|
15
20
|
record_observation(METRIC_CATEGORY, rv[0], 1)
|
16
21
|
advise_action(nil)
|
17
22
|
end
|
18
|
-
|
19
|
-
def overtime!
|
20
|
-
false
|
21
|
-
end
|
22
23
|
end
|
23
24
|
|
24
25
|
# Count 1 for each things located by the binding accessor
|
@@ -31,7 +32,7 @@ module Sqreen
|
|
31
32
|
@metric_category = rule_hash[Attrs::METRICS].first['name']
|
32
33
|
end
|
33
34
|
|
34
|
-
def post(rv, inst,
|
35
|
+
def post(rv, inst, args, _budget = nil, &_block)
|
35
36
|
return unless rv.is_a?(Array) && !rv.empty?
|
36
37
|
key = @accessors.map do |accessor|
|
37
38
|
accessor.resolve(binding, framework, inst, args, @data, rv)
|
@@ -9,7 +9,7 @@ module Sqreen
|
|
9
9
|
# FIXME: Factor with UserAgentMatchesCB
|
10
10
|
# Look for crawlers
|
11
11
|
class CrawlerUserAgentMatchesCB < MatcherRuleCB
|
12
|
-
def pre(_inst,
|
12
|
+
def pre(_inst, _args, _budget = nil, &_block)
|
13
13
|
ua = framework.client_user_agent
|
14
14
|
return unless ua
|
15
15
|
found = match(ua)
|
@@ -10,7 +10,7 @@ module Sqreen
|
|
10
10
|
class CrawlerUserAgentMatchesMetricsCB < MatcherRuleCB
|
11
11
|
CRAWLER_CATEGORY = 'crawler'.freeze
|
12
12
|
|
13
|
-
def pre(_inst,
|
13
|
+
def pre(_inst, _args, _budget = nil, &_block)
|
14
14
|
ua = framework.client_user_agent
|
15
15
|
return unless ua
|
16
16
|
found = match(ua)
|
@@ -17,6 +17,7 @@ module Sqreen
|
|
17
17
|
raise Sqreen::Exception, 'No data'
|
18
18
|
end
|
19
19
|
configure_custom_error(@data['values'][0])
|
20
|
+
@overtimeable = false
|
20
21
|
end
|
21
22
|
|
22
23
|
def configure_custom_error(custom_error)
|
@@ -31,7 +32,7 @@ module Sqreen
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
|
-
def failing(except, _inst,
|
35
|
+
def failing(except, _inst, _args, _budget = nil, &_block)
|
35
36
|
oexcept = nil
|
36
37
|
if except.respond_to?(:original_exception)
|
37
38
|
oexcept = except.original_exception
|
@@ -59,10 +60,6 @@ module Sqreen
|
|
59
60
|
}
|
60
61
|
[@status_code, headers, page]
|
61
62
|
end
|
62
|
-
|
63
|
-
def overtime!
|
64
|
-
false
|
65
|
-
end
|
66
63
|
end
|
67
64
|
end
|
68
65
|
end
|
@@ -8,7 +8,7 @@ else
|
|
8
8
|
begin
|
9
9
|
require 'mini_racer'
|
10
10
|
SQREEN_MINI_RACER = true
|
11
|
-
GC_MINI_RACER =
|
11
|
+
GC_MINI_RACER = 10_000
|
12
12
|
rescue LoadError
|
13
13
|
require 'therubyracer'
|
14
14
|
SQREEN_MINI_RACER = false
|
@@ -25,10 +25,43 @@ require 'sqreen/binding_accessor'
|
|
25
25
|
require 'sqreen/events/remote_exception'
|
26
26
|
|
27
27
|
module Sqreen
|
28
|
+
if SQREEN_MINI_RACER
|
29
|
+
# Context specialized for Sqreen usage
|
30
|
+
class SqreenContext < MiniRacer::Context
|
31
|
+
def eval_unsafe(str, filename = nil, timeoutv = nil)
|
32
|
+
# Beware, timeout could be kept in the context
|
33
|
+
# if perf cap is removed after having been activated
|
34
|
+
# As it's unused by execjscb we are not cleaning it
|
35
|
+
return super(str, filename) if timeoutv.nil?
|
36
|
+
return if timeoutv <= 0.0
|
37
|
+
timeoutv *= 1000 # Timeout are currently expressed in seconds
|
38
|
+
@timeout = timeoutv
|
39
|
+
@eval_thread = Thread.current
|
40
|
+
timeout do
|
41
|
+
super(str, filename)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Weak ref to a context
|
47
|
+
# enables us to skip a method missing call
|
48
|
+
class WeakCtx < WeakRef
|
49
|
+
def initialize(*args)
|
50
|
+
super(*args)
|
51
|
+
end
|
52
|
+
|
53
|
+
def eval_unsafe(str, filename, timeoutv)
|
54
|
+
__getobj__.eval_unsafe(str, filename, timeoutv)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
28
58
|
module Rules
|
29
59
|
# Exec js callbacks
|
30
60
|
class ExecJSCB < RuleCB
|
31
61
|
attr_accessor :restrict_max_depth
|
62
|
+
attr_reader :runtimes
|
63
|
+
attr_accessor :recycle_runtime_every
|
64
|
+
|
32
65
|
def initialize(klass, method, rule_hash)
|
33
66
|
super(klass, method, rule_hash)
|
34
67
|
callbacks = @rule[Attrs::CALLBACKS]
|
@@ -41,13 +74,15 @@ module Sqreen
|
|
41
74
|
end
|
42
75
|
|
43
76
|
build_runnable(callbacks)
|
44
|
-
|
77
|
+
@restrict_max_depth = 20
|
78
|
+
unless SQREEN_MINI_RACER
|
45
79
|
@compiled = ExecJS.compile(@source)
|
46
|
-
|
47
|
-
@snapshot = MiniRacer::Snapshot.new(@source)
|
48
|
-
@runtimes = []
|
80
|
+
return
|
49
81
|
end
|
50
|
-
@
|
82
|
+
@recycle_runtime_every = GC_MINI_RACER
|
83
|
+
@snapshot = MiniRacer::Snapshot.new(@source)
|
84
|
+
@runtimes = []
|
85
|
+
@key = "SQREEN_MINI_RACER_CONTEXT_#{object_id}".freeze
|
51
86
|
end
|
52
87
|
|
53
88
|
def pre?
|
@@ -62,22 +97,22 @@ module Sqreen
|
|
62
97
|
@js_failing
|
63
98
|
end
|
64
99
|
|
65
|
-
def pre(inst,
|
100
|
+
def pre(inst, args, budget = nil, &_block)
|
66
101
|
return unless pre?
|
67
102
|
|
68
|
-
call_callback('pre', inst, args)
|
103
|
+
call_callback('pre', inst, budget, args)
|
69
104
|
end
|
70
105
|
|
71
|
-
def post(rv, inst,
|
106
|
+
def post(rv, inst, args, budget = nil, &_block)
|
72
107
|
return unless post?
|
73
108
|
|
74
|
-
call_callback('post', inst, args, rv)
|
109
|
+
call_callback('post', inst, budget, args, rv)
|
75
110
|
end
|
76
111
|
|
77
|
-
def failing(rv, inst,
|
112
|
+
def failing(rv, inst, args, budget = nil, &_block)
|
78
113
|
return unless failing?
|
79
114
|
|
80
|
-
call_callback('failing', inst, args, rv)
|
115
|
+
call_callback('failing', inst, budget, args, rv)
|
81
116
|
end
|
82
117
|
|
83
118
|
def self.hash_val_included(needed, haystack, min_length = 8, max_depth = 20)
|
@@ -86,7 +121,7 @@ module Sqreen
|
|
86
121
|
to_do = haystack.map { |k, v| [new_obj, k, v, 0] }
|
87
122
|
until to_do.empty?
|
88
123
|
where, key, value, deepness = to_do.pop
|
89
|
-
safe_key = key.
|
124
|
+
safe_key = key.is_a?(Integer) ? key : key.to_s
|
90
125
|
if value.is_a?(Hash) && deepness < max_depth
|
91
126
|
val = {}
|
92
127
|
insert << [where, safe_key, val]
|
@@ -126,12 +161,12 @@ module Sqreen
|
|
126
161
|
def record_and_continue?(ret)
|
127
162
|
case ret
|
128
163
|
when NilClass
|
129
|
-
|
164
|
+
false
|
130
165
|
when Hash
|
131
166
|
ret.keys.each do |k|
|
132
167
|
ret[(begin
|
133
168
|
k.to_sym
|
134
|
-
rescue
|
169
|
+
rescue StandardError
|
135
170
|
k
|
136
171
|
end)] = ret[k] end
|
137
172
|
record_event(ret[:record]) unless ret[:record].nil?
|
@@ -141,15 +176,17 @@ module Sqreen
|
|
141
176
|
record_observation(*obs)
|
142
177
|
end
|
143
178
|
end
|
144
|
-
|
179
|
+
!ret[:call].nil?
|
145
180
|
else
|
146
181
|
raise Sqreen::Exception, "Invalid return type #{ret.inspect}"
|
147
182
|
end
|
148
183
|
end
|
149
184
|
|
150
185
|
def push_runtime(runtime)
|
151
|
-
@runtimes.delete_if do |th,
|
152
|
-
th.nil? || !th.weakref_alive? || !th.alive?
|
186
|
+
@runtimes.delete_if do |th, runt, _thid|
|
187
|
+
del = th.nil? || !th.weakref_alive? || !th.alive?
|
188
|
+
runt.dispose if del
|
189
|
+
del
|
153
190
|
end
|
154
191
|
@runtimes.push [WeakRef.new(Thread.current), runtime, Thread.current.object_id]
|
155
192
|
end
|
@@ -159,39 +196,41 @@ module Sqreen
|
|
159
196
|
runtime.dispose
|
160
197
|
end
|
161
198
|
|
162
|
-
def call_callback(name, inst, args, rv = nil)
|
199
|
+
def call_callback(name, inst, budget, args, rv = nil)
|
200
|
+
mini_racer_context = nil
|
163
201
|
if SQREEN_MINI_RACER
|
164
|
-
mini_racer_context = Thread.current[
|
165
|
-
|
166
|
-
|
167
|
-
push_runtime new_runtime
|
168
|
-
Thread.current["SQREEN_MINI_RACER_CONTEXT_#{object_id}"] = {
|
169
|
-
:c => 0,
|
170
|
-
:r => WeakRef.new(new_runtime),
|
171
|
-
}
|
172
|
-
elsif mini_racer_context[:c] >= GC_MINI_RACER
|
202
|
+
mini_racer_context = Thread.current[@key]
|
203
|
+
dead_runtime = !mini_racer_context || !mini_racer_context[:r] || !mini_racer_context[:r].weakref_alive?
|
204
|
+
if !dead_runtime && mini_racer_context[:c] >= @recycle_runtime_every
|
173
205
|
dispose_runtime(mini_racer_context[:r])
|
174
|
-
|
206
|
+
dead_runtime = true
|
207
|
+
end
|
208
|
+
if dead_runtime
|
209
|
+
new_runtime = SqreenContext.new(:snapshot => @snapshot)
|
175
210
|
push_runtime new_runtime
|
176
|
-
|
211
|
+
mini_racer_context = {
|
177
212
|
:c => 0,
|
178
|
-
:r =>
|
213
|
+
:r => WeakCtx.new(new_runtime),
|
179
214
|
}
|
215
|
+
Thread.current[@key] = mini_racer_context
|
180
216
|
end
|
181
217
|
end
|
182
218
|
ret = nil
|
183
219
|
args_override = nil
|
184
220
|
arguments = nil
|
185
|
-
|
221
|
+
while true
|
186
222
|
arguments = (args_override || @argument_requirements[name]).map do |accessor|
|
187
223
|
accessor.resolve(binding, framework, inst, args, @data, rv)
|
188
224
|
end
|
189
225
|
arguments = restrict(name, arguments) if @conditions.key?(name)
|
190
226
|
Sqreen.log.debug { [name, arguments].inspect }
|
191
227
|
if SQREEN_MINI_RACER
|
192
|
-
mini_racer_context = Thread.current["SQREEN_MINI_RACER_CONTEXT_#{object_id}"]
|
193
228
|
mini_racer_context[:c] += 1
|
194
|
-
|
229
|
+
begin
|
230
|
+
ret = mini_racer_context[:r].eval_unsafe("#{name}.apply(this, #{::JSON.generate(arguments)})", nil, budget)
|
231
|
+
rescue MiniRacer::ScriptTerminatedError
|
232
|
+
ret = nil
|
233
|
+
end
|
195
234
|
else
|
196
235
|
ret = @compiled.call(name, *arguments)
|
197
236
|
end
|
@@ -204,8 +243,8 @@ module Sqreen
|
|
204
243
|
args_override = ret[:args]
|
205
244
|
args_override = build_accessor(args_override) if args_override
|
206
245
|
end
|
207
|
-
rescue => e
|
208
|
-
Sqreen.log.warn "we catch a JScb exception: #{e.inspect}"
|
246
|
+
rescue StandardError => e
|
247
|
+
Sqreen.log.warn { "we catch a JScb exception: #{e.inspect}" }
|
209
248
|
Sqreen.log.debug e.backtrace
|
210
249
|
record_exception(e, :cb => name, :args => arguments)
|
211
250
|
nil
|
@@ -226,7 +265,7 @@ module Sqreen
|
|
226
265
|
|
227
266
|
def restrict(cbname, arguments)
|
228
267
|
condition = @conditions[cbname]
|
229
|
-
return arguments if condition.nil?
|
268
|
+
return arguments if condition.nil? || @argument_requirements[cbname].nil?
|
230
269
|
|
231
270
|
each_hash_val_include(condition) do |needle, haystack, min_length|
|
232
271
|
# We could actually run the binding accessor expression here.
|