Class: Contrast::Agent::Assess::Policy::Propagator::Split

Inherits:
Base
  • Object
show all
Extended by:
Components::Logger::InstanceMethods, Components::Scope::InstanceMethods, Utils::Assess::EventLimitUtils, Utils::Assess::SplitUtils
Defined in:
lib/contrast/agent/assess/policy/propagator/split.rb,
ext/cs__assess_yield_track/cs__assess_yield_track.c

Overview

This class is specifically for String#split & String#grapheme_clusters propagation it propagates tag ranges from a string to elements within an untracked array

Constant Summary collapse

SPLIT_TRACKER =
Contrast::Utils::ThreadTracker.new

Class Method Summary collapse

Methods included from Components::Scope::InstanceMethods

contrast_enter_method_scopes!, contrast_exit_method_scopes!, with_app_scope, with_contrast_scope, with_deserialization_scope, with_split_scope

Methods included from Components::Logger::InstanceMethods

cef_logger, logger

Methods included from Utils::Assess::EventLimitUtils

event_limit?, event_limit_for_rule?, increment_event_count

Methods inherited from Base

find_source, tracked_value?

Class Method Details

.instrument_string_splitObject

Load patch.



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/contrast/agent/assess/policy/propagator/split.rb', line 98

def instrument_string_split
  @_instrument_string_split ||= begin
    if ::Contrast::AGENT.patch_yield? && Funchook.available?
      require('cs__assess_yield_track/cs__assess_yield_track')
    end
    true
  rescue StandardError => e
    logger.error('Error loading split rb_yield patch', e)
    false
  end
end

.propagate(propagation_node, preshift, target) ⇒ nil

Propagate taint from a source as it is split into composite sections.

Parameters:

Returns:

  • (nil)

    so as not to risk changing the result of the propagation.



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/contrast/agent/assess/policy/propagator/split.rb', line 37

def propagate propagation_node, preshift, target
  return unless target.is_a?(Array) # apply_post_patch is called, but split with block returns a string.

  logger.trace('Propagation detected', node_id: propagation_node.id, target_id: target.__id__)

  source = find_source(propagation_node.sources[0], preshift)
  return unless (source_properties = Contrast::Agent::Assess::Tracker.properties(source))

  update_element_properties(propagation_node, target, preshift, source_properties)
  increment_event_count(propagation_node)
  nil
end

.propagate_yield(target) ⇒ Object

This method is called whenever an rb_yield is called. We need to leave it as soon as possible with as little work as possible.

Parameters:

  • target (String)

    the entity being passed to the yield block



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/contrast/agent/assess/policy/propagator/split.rb', line 81

def propagate_yield target
  return unless (source = SPLIT_TRACKER.get(:split_value)&.fetch(split_scope_depth))
  return unless (index = SPLIT_TRACKER.get(:split_index)&.fetch(split_scope_depth))
  return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))

  true_source = source[index]
  properties.copy_from(true_source, target)
rescue StandardError => e
  logger.warn('Unable to track within split context', e)
ensure
  if in_split_scope? && index
    idx = SPLIT_TRACKER.get(:split_index)
    idx[split_scope_depth] = index + 1 if defined?(idx) && idx.is_a?(Array)
  end
end

.wrap_split(string, args) ⇒ Object

Context for block split execution.

Parameters:

  • string (String)

    the String on which split is invoked.

  • args (Array<Object>)

    the arguments passed to the original split call.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/contrast/agent/assess/policy/propagator/split.rb', line 54

def wrap_split string, args
  # String#split start. Build context and yield.
  begin
    enter_split_scope!
    save_split_index!
    save_split_value!(string, args)
  rescue Exception => e # rubocop:disable Lint/RescueException
    logger.warn('Unable to record split context', e)
  end
  yield
ensure
  # String#split exit. Remove propagation context.
  begin
    exit_split_scope!
    unless in_split_scope?
      SPLIT_TRACKER.delete(:split_index)
      SPLIT_TRACKER.delete(:split_value)
    end
  rescue StandardError => e
    logger.warn('Unable to remove split context', e)
  end
end