lib/contrast/agent/assess/policy/propagator/split.rb in contrast-agent-3.10.2 vs lib/contrast/agent/assess/policy/propagator/split.rb in contrast-agent-3.11.0
- old
+ new
@@ -17,12 +17,29 @@
access_component :agent, :logging
SPLIT_TRACKER = Contrast::Utils::ThreadTracker.new
class << self
+ # Propagate taint from a source as it is split into composite
+ # sections. This method MUST return nil, otherwise it risks
+ # changing the result of of the propagation.
+ #
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
+ # the node that governs this propagation event.
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture
+ # of the state of the code just prior to the invocation of the
+ # patched method.
+ # @param target [Array, String] the target to which to propagate.
+ # @return [nil]
def propagate propagation_node, preshift, target
- return Contrast::Agent::Assess::Policy::Propagator::Keep.propagate(propagation_node, preshift, target) unless target.is_a?(Array)
+ logger.trace('Propagation detected',
+ node_id: propagation_node.id,
+ target_id: target.__id__)
+ unless target.is_a?(Array)
+ Contrast::Agent::Assess::Policy::Propagator::Keep.propagate(propagation_node, preshift, target)
+ return
+ end
source = find_source(propagation_node.sources[0], preshift)
separator_length = if propagation_node.method_name == :grapheme_clusters
# grapheme_clusters break the string apart based on each "user-perceived" character
@@ -47,10 +64,11 @@
end
elem.cs__properties.build_event(propagation_node, elem, preshift.object, target, preshift.args, 0)
elem.cs__properties.add_properties(propagation_node.properties)
current_index = current_index + elem_length + separator_length
end
+ nil
end
# Marks the point in which the String#split method is called.
# Responsible for building the context required to propagate when
# the results of #split are yielded directly to a block
@@ -64,11 +82,11 @@
save_split_index!(depth)
save_split_value!(depth, string, args)
rescue Exception => e # rubocop:disable Lint/RescueException
# don't let our errors propagate and disable String#split for
# this since we're in an error state
- logger.warn(e, 'Unable to record split context')
+ logger.warn('Unable to record split context', e)
end_split
end
# Marks the point in which the String#split method is exited.
# Responsible for removing the context required to propagate when
@@ -84,20 +102,22 @@
SPLIT_TRACKER.delete(:split_value)
else
SPLIT_TRACKER.set(:split_depth, depth)
end
rescue StandardError => e
- logger.warn(e, 'Unable to remove split context')
+ logger.warn('Unable to remove split context', e)
end
# 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.
#
# @param target [String] the entity being passed to the yield
# block
def propagate_yield target
+ depth, index = nil
+
depth = SPLIT_TRACKER.get(:split_depth)
return unless depth
source = SPLIT_TRACKER.get(:split_value)&.fetch(depth)
return unless source
@@ -106,13 +126,13 @@
return unless index
true_source = source[index]
target.cs__copy_from(true_source)
rescue StandardError => e
- logger.warn(e, 'Unable to track within split context')
+ logger.warn('Unable to track within split context', e)
ensure
- if defined?(depth) && defined?(index) && depth && index
+ if depth && index
idx = SPLIT_TRACKER.get(:split_index)
idx[depth] = index + 1 if defined?(idx) && idx.is_a?(Array)
end
end
@@ -120,10 +140,10 @@
if @_instrument_string_split.nil?
@_instrument_string_split = begin
cs__scoped_require 'cs__assess_yield_track/cs__assess_yield_track' if AGENT.patch_yield?
true
rescue StandardError => e
- logger.error(e, 'Error loading split rb_yield patch')
+ logger.error('Error loading split rb_yield patch', e)
false
end
end
@_instrument_string_split
end