lib/contrast/components/scope.rb in contrast-agent-5.1.0 vs lib/contrast/components/scope.rb in contrast-agent-5.2.0
- old
+ new
@@ -1,127 +1,134 @@
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
# frozen_string_literal: true
require 'fiber'
-require 'monitor'
require 'contrast/agent/scope'
+require 'cs__scope/cs__scope'
# This is the Scope component.
#
# It tracks /Contrast/ scope. That is, "are we currently doing assess or protect stuff within a patched method?" --
# this is how we avoid doing Contrast stuff on Contrast code or creating infinite loops -- or "are we in some other
# execution context for which we need to special case?".
module Contrast
module Components
- module Scope # :nodoc:
- MONITOR = Monitor.new
- EXECUTION_CONTEXT = {} # rubocop:disable Style/MutableConstant
-
- class Interface # :nodoc:
- def initialize
- # This is probably redundant with #scope_for_current_ec's nil check.
- EXECUTION_CONTEXT[Fiber.current] = Contrast::Agent::Scope.new
- end
-
- # This returns the scope governing the current execution context. Use this sparingly, preferring the instance
- # & class methods to access and query scope, rather than interacting with the scope object directly.
- def scope_for_current_ec
- MONITOR.synchronize do
- return EXECUTION_CONTEXT[Fiber.current] ||= Contrast::Agent::Scope.new
- end
- end
- end
-
- module InstanceMethods # :nodoc:
- # For each instance method on a scope, define a forwarder to the scope on the current execution context's scope.
- def scope_for_current_ec
- MONITOR.synchronize do
- return EXECUTION_CONTEXT[Fiber.current] ||= Contrast::Agent::Scope.new
- end
- end
-
- def enter_contrast_scope!
- scope_for_current_ec.enter_contrast_scope!
- end
-
- def enter_deserialization_scope!
- scope_for_current_ec.enter_deserialization_scope!
- end
-
- def enter_split_scope!
- scope_for_current_ec.enter_split_scope!
- end
-
- def enter_scope! name
- scope_for_current_ec.enter_scope! name
- end
-
- def exit_contrast_scope!
- scope_for_current_ec.exit_contrast_scope!
- end
-
- def exit_deserialization_scope!
- scope_for_current_ec.exit_deserialization_scope!
- end
-
- def exit_split_scope!
- scope_for_current_ec.exit_split_scope!
- end
-
- def exit_scope! name
- scope_for_current_ec.exit_scope! name
- end
-
- def in_contrast_scope?
- scope_for_current_ec.in_contrast_scope?
- end
-
- def in_deserialization_scope?
- scope_for_current_ec.in_deserialization_scope?
- end
-
- def in_split_scope?
- scope_for_current_ec.in_split_scope?
- end
-
- def split_scope_depth
- scope_for_current_ec.split_scope_depth
- end
-
- def in_scope? name
- scope_for_current_ec.in_scope? name
- end
-
+ # Constants defined in C:
+ #
+ # MONITOR = Mutex.new This was replaced from Monitor to Mutex.
+ # EXECUTION_CONTEXT = {} Hash containing all of the current ecs as keys pointing to their scope instances.
+ # EC_KEYS = [] set while we get the current ec, and used for sweeping the dead fibers in C.
+ #
+ # Methods defined in C:
+ #
+ # class Interface
+ # initializes the scope for the current fiber context.
+ # def initialize end;
+ #
+ # This returns the scope governing the current execution context. Use this sparingly, preferring the instance
+ # & class methods to access and query scope, rather than interacting with the scope object directly.
+ # def scope_for_current_ec end;
+ # end
+ #
+ # module Scope
+ # Singleton method for cleaning the dead fibers and unused scope instances, scope GC.
+ # def self.sweep_dead_ecs end;
+ # end
+ module Scope
+ # Methods defined in C:
+ #
+ # For each instance method on a scope, define a forwarder to the scope on the
+ # current execution context's scope.
+ # def scope_for_current_ec end;
+ #
+ # all the methods bellow are used as forwarders to be executed in the current ec.
+ # exp: in_contrast_scope? => scope_for_current_ec.enter_contrast_scope!
+ #
+ # Check if we are in contrast scope.
+ # def in_contrast_scope? end;
+ # @return [Boolean] check if we are in contrast scope
+ # if the scope is above 0 return true.
+ #
+ # check if we are in deserialization scope.
+ # def in_deserialization_scope? end;
+ # @return [Boolean] check if we are in contrast scope
+ # if the scope is above 0 return true.
+ #
+ # check if we are in split scope.
+ # def in_split_scope? end;
+ # @return [Boolean] check if we are in contrast scope
+ # if the scope is above 0 return true.
+ #
+ # enter contrast scope.
+ # def enter_contrast_scope! end;
+ # @return @contrast_scope [Integer] contrast scope increased.
+ #
+ # enter deserialization scope.
+ # def enter_deserialization_scope! end;
+ # @return @deserialization_scope [Integer] deserialization scope increased.
+ #
+ # enter split scope.
+ # def enter_split_scope! end;
+ # @return @split_scope [Integer] split scope increased.
+ #
+ # check split scope depth.
+ # def split_scope_depth end;
+ # @return @split_scope [Integer] split scope depth.
+ #
+ # exit contrast scope.
+ # def exit_contrast_scope! end;
+ # @return @contrast_scope [Integer] contrast scope decreased.
+ #
+ # exit deserialization scope.
+ # def exit_deserialization_scope! end;
+ # @return @deserialization_scope [Integer] deserialization scope decreased.
+ #
+ # exit split scope.
+ # def exit_split_scope! end;
+ # @return @split_scope [Integer] split scope decreased.
+ #
+ # Static methods to be used, the cases are defined by the usage from the above methods
+ #
+ # check if are in specific scope.
+ # def in_scope? name end;
+ # @param name [Symbol] scope symbol representing scope to check.
+ # @return [Boolean] check if we are in passed scope.
+ #
+ # enter specific scope.
+ # def enter_scope! name end;
+ # @param name [Symbol] scope symbol representing scope to enter.
+ # @return scope [Integer] entered scope value increased.
+ #
+ # exit specific scope.
+ # def exit_cope! name end;
+ # @param name [Symbol] scope symbol representing scope to exit.
+ # @return scope [Integer] entered scope value decreased.
+ module InstanceMethods
+ # Forwarder to execute block in contrast scope under current
+ # method execution context. On completion exits scope.
def with_contrast_scope
scope_for_current_ec.enter_contrast_scope!
yield
ensure
scope_for_current_ec.exit_contrast_scope!
end
+ # Forwarder to execute block in deserialization scope under current
+ # method execution context. On completion exits scope.
def with_deserialization_scope
scope_for_current_ec.enter_deserialization_scope!
yield
ensure
scope_for_current_ec.exit_deserialization_scope!
end
+ # Forwarder to execute block in split scope under current
+ # method execution context. On completion exits scope.
def with_split_scope
scope_for_current_ec.enter_split_scope!
yield
ensure
scope_for_current_ec.exit_split_scope!
- end
- end
-
- def self.sweep_dead_ecs
- # TODO: RUBY-534, #sweep_dead_ecs compensates for a lack of weak tables. when we can use WeakRef, we should
- # investigate removing this call and instead use the WeakRef for the Execution Context's Keys or using our
- # Finalizers Hash for Fibers
- MONITOR.synchronize do
- EXECUTION_CONTEXT.delete_if do |ec, _scope|
- !ec.alive?
- end
end
end
ClassMethods = InstanceMethods
end