# Copyright (c) 2023 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 beginning of the target. The target's preexisting # tags are shifted to account for this. class Prepend < Contrast::Agent::Assess::Policy::Propagator::Base class << self # For the source, prepend its tags to the target. It's basically the # opposite of append. :-P def propagate propagation_node, preshift, target return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target)) sources = propagation_node.sources # source1 is the copy of the thing being prepended to source1 = find_source(sources[0], preshift) # source2 is the copy of the thing being prepended source2 = sources[1] ? find_source(sources[1], preshift) : source1 original_start_index = target.rindex(source1) || 0 # if the object and the return are the same length just copy the # tags from the object(since nothing from args was added to # return) if source1.length == target.length properties.copy_from(source1, target, 0, propagation_node.untags) else # find original in the target, copy tags to the new position in target properties.copy_from(source1, target, original_start_index, propagation_node.untags) # then we add the tags from the thing prepended to the start # of the target start = 0 while start < original_start_index properties.copy_from(source2, target, start, propagation_node.untags) start += source2.length next unless start > original_start_index properties.tags_at(start - source2.length).each do |tag| tag.update_end(original_start_index) end end end # and finally merge the tags if any overlap. properties.cleanup_tags end end end end end end end end