# 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 # This class is specifically for String#tr(_s) propagation # # Disclaimer: there may be a better way, but we're # in a 'get it work' state. hopefully, we'll be in # a 'get it right' state soon. class Trim class << self def tr_tagger patcher, preshift, ret, _block return ret unless ret && !ret.empty? source = preshift.object args = preshift.args ret.cs__copy_from(source) replace_string = args[1] source_chars = source.chars # if the replace string is empty, then there's a bunch of deletes. this # functions the same as the Removal propagation. if replace_string == Contrast::Utils::ObjectShare::EMPTY_STRING Contrast::Agent::Assess::Policy::Propagator::Remove.handle_removal(source_chars, ret) else remove_ranges = [] ret_chars = ret.chars curr_span = nil source_chars.each_with_index do |char, idx| if ret_chars[idx] == char next unless curr_span curr_span.stop = idx remove_ranges << curr_span curr_span = nil else curr_span ||= Contrast::Agent::Assess::AdjustedSpan.new(idx) end end # account for the last char being different if curr_span curr_span.stop = source_chars.length remove_ranges << curr_span end ret.cs__properties.delete_tags_at_ranges(remove_ranges, false) end ret.cs__properties.build_event( patcher, ret, source, ret, args, 1) ret end def tr_s_tagger patcher, preshift, ret, _block return unless ret && !ret.empty? source = preshift.object args = preshift.args source.cs__splat_tags(ret) ret.cs__properties.build_event( patcher, ret, source, ret, args) ret end end end end end end end end