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