lib/contrast/extension/assess/assess_extension.rb in contrast-agent-3.13.2 vs lib/contrast/extension/assess/assess_extension.rb in contrast-agent-3.14.0
- old
+ new
@@ -1,57 +1,44 @@
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
# frozen_string_literal: true
-cs__scoped_require 'contrast/agent/assess/properties'
-cs__scoped_require 'contrast/agent/assess/insulator'
+require 'contrast/agent/assess/properties'
+require 'contrast/agent/assess/finalizers/finalize'
module Contrast
module Extension
module Assess
# This module is responsible for maintaining the data we need to
# construct a trace event for the object in which it is included. Rather
# than have this code all over the place, any class that wants to use
# dataflow features should be sent
# 'include Contrast::Extension::Assess::AssessExtension'
module AssessExtension
+ def cs__transfer_properties dup
+ Contrast::Agent::Assess::Finalizers::Finalize::PROPERTIES_HASH[dup] ||= Contrast::Agent::Assess::Finalizers::Finalize::PROPERTIES_HASH[self].dup
+ end
+
# Lazily build properties object. Only objects that have been tracked
# will have the @_cs__properties, but all will respond to the
# cs__properties method call. You should only call this method if you
# either intend to start tracking an object or you have already checked
# cs__tracked? and it is true.
def cs__properties
- # If this object was tracked before being frozen, it'll have
- # mutable properties we need inside of the insulator @_cs__properties
- if cs__frozen?
- if instance_variable_defined?(:@_cs__properties)
- @_cs__properties.properties
- else
- Contrast::Agent::Assess::Insulator.generate_frozen.properties
- end
- else
- @_cs__properties ||= Contrast::Agent::Assess::Insulator.generate
- @_cs__properties.properties
- end
+ Contrast::Agent::Assess::Finalizers::Finalize::PROPERTIES_HASH[self] ||= Contrast::Agent::Assess::Properties.new
end
- def cs__properties?
- instance_variable_defined?(:@_cs__properties)
- end
-
# This is a way to check if we are already tracking an object without
# adding tracking to it. If the object already has been tracked we will
# return the tracking state of its properties. If the object hasn't
# already been tracked we will return false without starting to track
# it
def cs__tracked?
- cs__properties? && cs__properties.tracked?
+ !!Contrast::Agent::Assess::Finalizers::Finalize::PROPERTIES_HASH[self]&.tracked?
end
def cs__reset_properties
- return unless cs__properties?
-
- @_cs__properties = nil
+ Contrast::Agent::Assess::Finalizers::Finalize::PROPERTIES_HASH[self] = nil
end
# copy tags and info from object to self if object support methods
# obj: the object from which to copy tags and events
# shift: how far to shift the tags, negative moves left
@@ -59,18 +46,13 @@
def cs__copy_from obj, shift = 0, skip_tags = nil
return if obj.equal?(self)
return unless Contrast::Utils::DuckUtils.quacks_to?(obj,
:cs__tracked?)
return unless obj.cs__tracked?
- return if cs__properties == Contrast::Agent::Assess::Insulator.generate_frozen.properties
+ return unless cs__properties
- # This was fun to find...
- # the clone and dup methods don't apply to instance variables in the
- # cloned/ duped thing, so the arrays in the properties were the same.
- # The most infinite of infinite loops ensued.
- # DO NOT TAKE THIS OUT!
- cs__reset_properties if obj.cs__properties == cs__properties
+ cs__adjust_duplicate(obj)
obj.cs__properties.events.each do |event|
cs__properties.events << event
end
@@ -138,9 +120,25 @@
existing.each do |range|
range.update_end(length) if range.end_idx > length
end
end
+ end
+
+ private
+
+ # Because of how our tracking works now, sometimes the Source and
+ # Target are the same, but their IDs in our map will be different due
+ # to PreShift duplication. To account for this, we have to ensure that
+ # the Object we're copying from does not have the same Properties
+ # that the Object we're copying to does. If they are the same, wipe the
+ # Target so that the copy method can update events and ranges as
+ # necessary.
+ # DO NOT TAKE THIS OUT!
+ def cs__adjust_duplicate obj
+ cs__reset_properties if obj.cs__properties == cs__properties
+ cs__reset_properties if obj.cs__properties.__id__ == cs__properties.dupped_from
+ cs__reset_properties if obj.cs__properties.dupped_from == cs__properties.__id__
end
end
end
end
end