sqreen 1.14.1-java → 1.14.2-java

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
  SHA256:
3
- metadata.gz: 625e0b54a85e128be8a54aa94d91ff58d2dd99556fb6cfc79e22511731082fd3
4
- data.tar.gz: 19ef99856cdc8269acf7888c424f2f80fdea4643b3c7deef4fa963f1de127923
3
+ metadata.gz: d64ca79b53ae2456a2c51b3939ff14c2d41b8dd82a7ce89860d82005cc75e1e5
4
+ data.tar.gz: fdee9e1364ff14e4167ae07bc9c1d878a073904a32d79acccbc1a041d96555c0
5
5
  SHA512:
6
- metadata.gz: bbe599eea8b8f74ced0183e8ec6a2de5bc5cfd9506618fb21e5b526cca2611ed77cf94765abd39c8f136584c9f88fd7747f3ac29bd0729b57c9f5e647a7dfba1
7
- data.tar.gz: 510eaa669c74a5989023b4b08da5158dd97e0e65e847301510e0c2e457e674b4b360c80a2996708aef37b05dd04fc5a56013278cc1003ed9c6f4e6fcf6acba5f
6
+ metadata.gz: 5a4b42b30b81fa25b154ccb5dea089dcd46ddb54c08fcb7e55946c8b45a03c74e4420bba338590b48582b3fea2084111c76b7ddffc4ff7fe862a0670e94ff5aa
7
+ data.tar.gz: 78e5b14939b1c743335b17fdaf9bc3d2d954c1806326edf4c88a2a58e5a170f87cf642bd8750caed162ec0090220b0d733f02cb38d3714403c46d8654cc249be
data/lib/sqreen.rb CHANGED
@@ -17,6 +17,10 @@ require 'thread'
17
17
  # Auto start the instrumentation.
18
18
 
19
19
  Sqreen.framework.on_start do |framework|
20
+ if RUBY_VERSION =~ /\A2\.5\.[01]\z/ && Sqreen.framework.on_pre_fork_preload?
21
+ STDERR.puts("Avoiding launching sqreen thread pre-fork") # sqreen log unavailable
22
+ next
23
+ end
20
24
  Thread.new do
21
25
  begin
22
26
  runner = nil
@@ -422,6 +422,15 @@ module Sqreen
422
422
  end
423
423
  end
424
424
 
425
+ def on_pre_fork_preload?
426
+ # unlike with worker_fork_detection, we can't be instrument Puma::Cluster
427
+ # in time for intercepting run
428
+ stack = Kernel.caller_locations
429
+
430
+ puma_preload?(stack) || unicorn_preload?(stack)
431
+ end
432
+
433
+
425
434
  protected
426
435
 
427
436
  # Is this a whitelisted path?
@@ -519,6 +528,7 @@ module Sqreen
519
528
  Sqreen.log.warn "Failed ignoring AttackBlocked on NewRelic: #{e.inspect}"
520
529
  end
521
530
 
531
+ # if it doesn't detect the fork it's not a problem
522
532
  def worker_fork_detection
523
533
  # only Puma currently supported
524
534
  return unless defined?(Puma::Cluster) && Puma::Cluster.instance_methods.include?(:worker)
@@ -533,6 +543,22 @@ module Sqreen
533
543
 
534
544
  private
535
545
 
546
+ def puma_preload?(stack)
547
+ cluster_run = stack.each_with_index.find { |b, _i| b.path =~ /puma\/cluster\.rb\z/ && b.label == 'run' }
548
+ return false unless cluster_run
549
+ frame_atop = stack[cluster_run[1] - 1]
550
+ frame_atop.label == 'load_and_bind'
551
+ end
552
+
553
+ def unicorn_preload?(stack)
554
+ build_app = stack.each_with_index.find do |b, _i|
555
+ b.path =~ /unicorn\/http_server\.rb\z/ && b.label == 'build_app!'
556
+ end
557
+ return false unless build_app
558
+ frame_below = stack[build_app[1] + 1]
559
+ frame_below.label == 'start'
560
+ end
561
+
536
562
  def split_ip_addresses(ip_addresses)
537
563
  ip_addresses ? ip_addresses.strip.split(/[,\s]+/) : []
538
564
  end
@@ -1,15 +1,26 @@
1
1
  require 'execjs'
2
+ require 'weakref'
2
3
 
3
4
  module Sqreen
4
5
  module Js
5
6
  class ExecjsAdapter < JsServiceAdapter
6
- def preprocess(_rule_name, code)
7
- ExecJsRunnable.new(ExecJS.compile(code))
7
+ def preprocess(rule_name, code)
8
+ if thread_safe?
9
+ ExecJsRunnable.new(ExecJS.compile(code))
10
+ else
11
+ ThreadLocalExecJsRunnable.new(code)
12
+ end
8
13
  end
9
14
 
10
15
  def variant_name
11
16
  ExecJS.runtime.name + ' (ExecJS)'
12
17
  end
18
+
19
+ private
20
+
21
+ def thread_safe?
22
+ ExecJS.runtime.name != 'therubyrhino (Rhino)'
23
+ end
13
24
  end
14
25
 
15
26
  class ExecJsRunnable < ExecutableJs
@@ -21,5 +32,42 @@ module Sqreen
21
32
  @compiled.call(cbname, *arguments)
22
33
  end
23
34
  end
35
+
36
+ class ThreadLocalExecJsRunnable < ExecutableJs
37
+ def initialize(code)
38
+ @code = code
39
+ @tl_key = "SQREEN_EXECJS_CONTEXT_#{object_id}".freeze
40
+ @runtimes = [] # place where to keep strong references
41
+ @runtimes_mutex = Mutex.new
42
+ end
43
+
44
+ def run_js_cb(cbname, _budget, arguments)
45
+ tl_exec_js_runnable.call(cbname, *arguments)
46
+ end
47
+
48
+ def with_runtimes_mutex
49
+ @runtimes_mutex.synchronize { yield }
50
+ end
51
+
52
+ private
53
+
54
+ def dispose_from_dead_threads
55
+ with_runtimes_mutex do
56
+ @runtimes.delete_if { |th, _runtime| !th.alive? }
57
+ end
58
+ end
59
+
60
+ def tl_exec_js_runnable
61
+ runnable = Thread.current[@tl_key]
62
+ return runnable if runnable && runnable.weakref_alive?
63
+
64
+ dispose_from_dead_threads
65
+ runtime = ExecJS.compile(@code)
66
+ with_runtimes_mutex do
67
+ @runtimes << [Thread.current, runtime]
68
+ end
69
+ Thread.current[@tl_key] = WeakRef.new(runtime)
70
+ end
71
+ end
24
72
  end
25
73
  end
@@ -5,7 +5,7 @@ module Sqreen
5
5
  # start public interface
6
6
 
7
7
  class JsService
8
- include Singleton
8
+ include ::Singleton
9
9
 
10
10
  def initialize
11
11
  detect_adapter
@@ -75,7 +75,7 @@ module Sqreen
75
75
  # end public interface
76
76
 
77
77
  class JsServiceAdapter
78
- def preprocess(code)
78
+ def preprocess(rule_name, code)
79
79
  raise Sqreen::NotImplementedYet
80
80
  end
81
81
 
@@ -1,4 +1,5 @@
1
1
  require 'weakref'
2
+ require 'sqreen/runner' # for Sqreen.on_forked_worker?
2
3
 
3
4
  module Sqreen
4
5
  module Js
@@ -63,8 +64,9 @@ module Sqreen
63
64
 
64
65
  mini_racer_context[:c] += 1
65
66
  begin
67
+ json_args = "[#{arguments.map(&method(:fixup_bad_encoding)).map(&:to_json).join(',')}]"
66
68
  mini_racer_context[:r].eval_unsafe(
67
- "#{cb_name}.apply(this, #{::JSON.generate(arguments)})", nil, budget)
69
+ "#{cb_name}.apply(this, #{json_args})", nil, budget)
68
70
  rescue @module::ScriptTerminatedError
69
71
  nil
70
72
  end
@@ -72,6 +74,23 @@ module Sqreen
72
74
 
73
75
  private
74
76
 
77
+ def fixup_bad_encoding(arg)
78
+ # NOTE: we don't fix encoding problems in deeper structures
79
+ return arg unless arg.is_a?(String)
80
+ unless arg.valid_encoding?
81
+ return arg.dup.force_encoding(Encoding::ISO_8859_1)
82
+ end
83
+
84
+ # encoding is valid if it reaches this point
85
+ return arg if arg.encoding == Encoding::UTF_8
86
+
87
+ begin
88
+ arg.encode(Encoding::UTF_8)
89
+ rescue Encoding::UndefinedConversionError
90
+ arg.dup.force_encoding(Encoding::ISO_8859_1)
91
+ end
92
+ end
93
+
75
94
  def snapshot
76
95
  @snapshot ||= @module::Snapshot.new(@source)
77
96
  end
@@ -58,6 +58,8 @@ module Sqreen
58
58
 
59
59
  finish_time = SQREEN_MONO_TIME ? Time.now.utc : finish
60
60
  time_millis = (finish - start) * 1000
61
+ # Ensure we always have a timings if we somehow missed the request start
62
+ SharedStorage[:sqreen_request_time] ||= 0
61
63
  SharedStorage[:sqreen_request_time] += time_millis
62
64
  metrics_store.update(metric_name, finish_time, nil, time_millis)
63
65
  end
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
2
  # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
3
  module Sqreen
4
- VERSION = '1.14.1'.freeze
4
+ VERSION = '1.14.2'.freeze
5
5
  end
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.14.1
4
+ version: 1.14.2
5
5
  platform: java
6
6
  authors:
7
7
  - Sqreen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-21 00:00:00.000000000 Z
11
+ date: 2018-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement