# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true module Contrast module Agent module Assess module Policy module Propagator # Propagation that results in all the tags of the source being # applied to the target at its middle. The target's preexisting tags # are unaffected beyond any merging of overlapping tags. class Center < Contrast::Agent::Assess::Policy::Propagator::Base class << self def propagate propagation_node, preshift, target return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target)) sources = propagation_node.sources source1 = find_source(sources[0], preshift) if source1.length == target.length properties.copy_from(source1, target, 0, propagation_node.untags) properties.cleanup_tags return end # find original in the target, copy tags to the new position in target original_start_index = target[0..(target.length / 2) + 1].rindex(source1) original_start_index ||= 1 properties.copy_from(source1, target, original_start_index, propagation_node.untags) return unless sources[1] original_end_index = original_start_index + source1.length - 1 handle_incoming_tags(target, propagation_node, sources[1], preshift, original_start_index, original_end_index) end private # If the input passed in to wrap around the existing object has # tags, we have to prepend and append those tags to the centered # value. # @param target [Object] the thing to apply tags to. # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] # the node that indicates how this propagation should be # handled. # @param source_location [String] the marker to indicate where in # the preshift the source is located. # @param preshift [Contrast::Agent::Assess::Preshift] the state # of the call before the method was executed. # @param start_index [Integer] where the centered object starts. # @param end_index [Integer] where the centered object ends. def handle_incoming_tags target, propagation_node, source_location, preshift, start_index, end_index source = find_source(source_location, preshift) iterate_tags(target, propagation_node, source, 0, start_index) iterate_tags(target, propagation_node, source, end_index, target.length) end def iterate_tags target, propagation_node, source, start, stop properties = Contrast::Agent::Assess::Tracker.properties(target) while start < stop properties.copy_from(source, target, start, propagation_node.untags) start += source.length next unless start > stop properties.tags_at(start - source.length).each do |tag| tag.update_end(stop) end end end end end end end end end end