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_split ⇒ Object

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.



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.



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.



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