sqreen 1.14.1-java → 1.14.2-java

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 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