# Copyright (c) 2020 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 end of the target. The target's preexisting tags are # unaffected beyond any merging of overlapping tags. class Append < Contrast::Agent::Assess::Policy::Propagator::Base class << self # For the source, append its tags to the target. # if the target length is greater than the source # copy tags from the param to the target in chunks of param size or less # if param is appended in space less than param length def propagate propagation_node, preshift, target properties = Contrast::Agent::Assess::Tracker.properties(target) return unless properties sources = propagation_node.sources source1 = find_source(sources[0], preshift) # Some appends have two args. If they don't this is probably something # obnoxious, like String.* source2 = sources[1] ? find_source(sources[1], preshift) : source1 # 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 original_start_index = target.index(source1) properties.copy_from(source1, target, original_start_index, propagation_node.untags) start = original_start_index + source1.length while start < target.length properties.copy_from(source2, target, start, propagation_node.untags) start += source2.length next unless start > target.length properties.tags_at(start - source2.length).each do |tag| tag.update_end(target.length) end end end properties.cleanup_tags end end end end end end end end