contrast-agent 3.14.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +18 -15
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +1 -0
- data/ext/cs__assess_string/cs__assess_string.c +24 -25
- data/ext/cs__assess_string/cs__assess_string.h +3 -1
- data/ext/cs__common/cs__common.c +4 -2
- data/ext/cs__common/cs__common.h +1 -1
- data/lib/contrast.rb +1 -1
- data/lib/contrast/agent/assess.rb +1 -0
- data/lib/contrast/agent/assess/contrast_event.rb +4 -12
- data/lib/contrast/agent/assess/finalizers/freeze.rb +3 -1
- data/lib/contrast/agent/assess/finalizers/hash.rb +45 -1
- data/lib/contrast/agent/assess/policy/patcher.rb +1 -1
- data/lib/contrast/agent/assess/policy/policy.rb +0 -2
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +0 -1
- data/lib/contrast/agent/assess/policy/preshift.rb +7 -11
- data/lib/contrast/agent/assess/policy/propagation_method.rb +50 -33
- data/lib/contrast/agent/assess/policy/propagator/append.rb +8 -5
- data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/center.rb +9 -5
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +5 -3
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +6 -3
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +4 -1
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +6 -6
- data/lib/contrast/agent/assess/policy/propagator/next.rb +7 -5
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +8 -5
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +8 -4
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +5 -2
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +7 -5
- data/lib/contrast/agent/assess/policy/propagator/select.rb +15 -7
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +14 -8
- data/lib/contrast/agent/assess/policy/propagator/split.rb +14 -8
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +30 -21
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +11 -5
- data/lib/contrast/agent/assess/policy/source_method.rb +85 -58
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +16 -11
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +1 -1
- data/lib/contrast/agent/assess/policy/trigger_method.rb +38 -15
- data/lib/contrast/agent/assess/policy/trigger_node.rb +14 -13
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +2 -1
- data/lib/contrast/agent/assess/properties.rb +2 -0
- data/lib/contrast/agent/assess/property/updated.rb +136 -0
- data/lib/contrast/agent/assess/tracker.rb +66 -0
- data/lib/contrast/agent/class_reopener.rb +7 -5
- data/lib/contrast/agent/middleware.rb +0 -1
- data/lib/contrast/agent/patching/policy/patcher.rb +13 -22
- data/lib/contrast/agent/patching/policy/policy.rb +1 -4
- data/lib/contrast/agent/response.rb +17 -6
- data/lib/contrast/agent/rewriter.rb +1 -3
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/communication/messaging_queue.rb +1 -4
- data/lib/contrast/api/decorators/application_update.rb +2 -4
- data/lib/contrast/api/decorators/trace_event.rb +5 -5
- data/lib/contrast/components/app_context.rb +11 -9
- data/lib/contrast/components/config.rb +3 -13
- data/lib/contrast/components/contrast_service.rb +2 -2
- data/lib/contrast/config/application_configuration.rb +5 -2
- data/lib/contrast/config/service_configuration.rb +8 -2
- data/lib/contrast/configuration.rb +88 -47
- data/lib/contrast/extension/assess.rb +0 -2
- data/lib/contrast/extension/assess/array.rb +8 -5
- data/lib/contrast/extension/assess/erb.rb +6 -3
- data/lib/contrast/extension/assess/fiber.rb +9 -9
- data/lib/contrast/extension/assess/hash.rb +2 -3
- data/lib/contrast/extension/assess/kernel.rb +12 -5
- data/lib/contrast/extension/assess/marshal.rb +3 -2
- data/lib/contrast/extension/assess/regexp.rb +5 -4
- data/lib/contrast/extension/assess/string.rb +8 -10
- data/lib/contrast/framework/rack/patch/session_cookie.rb +12 -18
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +4 -10
- data/lib/contrast/framework/rails/support.rb +2 -0
- data/lib/contrast/logger/application.rb +11 -3
- data/lib/contrast/utils/assess/tracking_util.rb +48 -3
- data/lib/contrast/utils/duck_utils.rb +0 -10
- data/lib/contrast/utils/env_configuration_item.rb +2 -1
- data/lib/contrast/utils/invalid_configuration_util.rb +21 -19
- data/lib/contrast/utils/string_utils.rb +10 -5
- data/resources/assess/policy.json +0 -10
- data/ruby-agent.gemspec +16 -15
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +42 -21
- data/lib/contrast/agent/assess/finalizers/finalize.rb +0 -21
- data/lib/contrast/extension/assess/assess_extension.rb +0 -145
- data/lib/contrast/utils/freeze_util.rb +0 -32
@@ -16,6 +16,9 @@ module Contrast
|
|
16
16
|
# copy tags from the param to the target in chunks of param size or less
|
17
17
|
# if param is appended in space less than param length
|
18
18
|
def propagate propagation_node, preshift, target
|
19
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
20
|
+
return unless properties
|
21
|
+
|
19
22
|
sources = propagation_node.sources
|
20
23
|
source1 = find_source(sources[0], preshift)
|
21
24
|
# Some appends have two args. If they don't this is probably something
|
@@ -25,25 +28,25 @@ module Contrast
|
|
25
28
|
# if the object and the return are the same length just copy the tags
|
26
29
|
# from the object(since nothing from args was added to return)
|
27
30
|
if source1.length == target.length
|
28
|
-
|
31
|
+
properties.copy_from(source1, target, 0, propagation_node.untags)
|
29
32
|
else
|
30
33
|
# find original in the target, copy tags to the new position in
|
31
34
|
# target
|
32
35
|
original_start_index = target.index(source1)
|
33
|
-
|
36
|
+
properties.copy_from(source1, target, original_start_index, propagation_node.untags)
|
34
37
|
|
35
38
|
start = original_start_index + source1.length
|
36
39
|
while start < target.length
|
37
|
-
|
40
|
+
properties.copy_from(source2, target, start, propagation_node.untags)
|
38
41
|
start += source2.length
|
39
42
|
next unless start > target.length
|
40
43
|
|
41
|
-
|
44
|
+
properties.tags_at(start - source2.length).each do |tag|
|
42
45
|
tag.update_end(target.length)
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
46
|
-
|
49
|
+
properties.cleanup_tags
|
47
50
|
end
|
48
51
|
end
|
49
52
|
end
|
@@ -12,19 +12,22 @@ module Contrast
|
|
12
12
|
class Center < Contrast::Agent::Assess::Policy::Propagator::Base
|
13
13
|
class << self
|
14
14
|
def propagate propagation_node, preshift, target
|
15
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
16
|
+
return unless properties
|
17
|
+
|
15
18
|
sources = propagation_node.sources
|
16
19
|
source1 = find_source(sources[0], preshift)
|
17
20
|
|
18
21
|
if source1.length == target.length
|
19
|
-
|
20
|
-
|
22
|
+
properties.copy_from(source1, target, 0, propagation_node.untags)
|
23
|
+
properties.cleanup_tags
|
21
24
|
return
|
22
25
|
end
|
23
26
|
|
24
27
|
# find original in the target, copy tags to the new position in target
|
25
28
|
original_start_index = target[0..target.length / 2 + 1].rindex(source1)
|
26
29
|
original_start_index ||= 1
|
27
|
-
|
30
|
+
properties.copy_from(source1, target, original_start_index, propagation_node.untags)
|
28
31
|
|
29
32
|
return unless sources[1]
|
30
33
|
|
@@ -54,12 +57,13 @@ module Contrast
|
|
54
57
|
end
|
55
58
|
|
56
59
|
def iterate_tags target, propagation_node, source, start, stop
|
60
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
57
61
|
while start < stop
|
58
|
-
|
62
|
+
properties.copy_from(source, target, start, propagation_node.untags)
|
59
63
|
start += source.length
|
60
64
|
next unless start > stop
|
61
65
|
|
62
|
-
|
66
|
+
properties.tags_at(start - source.length).each do |tag|
|
63
67
|
tag.update_end(stop)
|
64
68
|
end
|
65
69
|
end
|
@@ -31,12 +31,15 @@ module Contrast
|
|
31
31
|
next unless value
|
32
32
|
next if known_tainted&.include?(key)
|
33
33
|
|
34
|
+
properties = Contrast::Agent::Assess::Tracker.properties(value)
|
35
|
+
next unless properties
|
36
|
+
|
34
37
|
# TODO: RUBY-540 handle sanitization, handle nested objects
|
35
38
|
Contrast::Agent::Assess::Policy::PropagationMethod.apply_tags(propagation_node, value)
|
36
|
-
|
39
|
+
properties.build_event(propagation_node, value, preshift.object, target, preshift.args)
|
37
40
|
next unless tracked_value?(value)
|
38
41
|
|
39
|
-
tainted_columns[key] =
|
42
|
+
tainted_columns[key] = properties
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
@@ -45,7 +48,6 @@ module Contrast
|
|
45
48
|
if known_tainted
|
46
49
|
known_tainted.concat(tainted_columns.keys)
|
47
50
|
else
|
48
|
-
class_type.send(:include, Contrast::Extension::Assess::AssessExtension) unless class_type < Contrast::Extension::Assess::AssessExtension
|
49
51
|
ASSESS.tainted_columns[class_name] = tainted_columns.keys
|
50
52
|
end
|
51
53
|
|
@@ -16,6 +16,9 @@ module Contrast
|
|
16
16
|
# Unlike additive propagation, this currently only supports one source
|
17
17
|
# We assume that insert changes the preshift target
|
18
18
|
def propagate propagation_node, preshift, target
|
19
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
20
|
+
return unless properties
|
21
|
+
|
19
22
|
source = find_source(propagation_node.sources[0], preshift)
|
20
23
|
|
21
24
|
patcher_target = propagation_node.targets[0]
|
@@ -38,10 +41,10 @@ module Contrast
|
|
38
41
|
overflow = insert_point...(insert_point + source.length)
|
39
42
|
|
40
43
|
# handle shifting the inserted range
|
41
|
-
|
44
|
+
properties.shift_tags([overflow])
|
42
45
|
|
43
|
-
|
44
|
-
|
46
|
+
properties.copy_from(source, target, insert_point, propagation_node.untags)
|
47
|
+
properties.cleanup_tags
|
45
48
|
end
|
46
49
|
end
|
47
50
|
end
|
@@ -14,8 +14,11 @@ module Contrast
|
|
14
14
|
# Keep means the tags just pass from the source to the target
|
15
15
|
# as is.
|
16
16
|
def propagate propagation_node, preshift, target
|
17
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
18
|
+
return unless properties
|
19
|
+
|
17
20
|
source = find_source(propagation_node.sources[0], preshift)
|
18
|
-
|
21
|
+
properties.copy_from(source, target, 0, propagation_node.untags)
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
@@ -67,18 +67,18 @@ module Contrast
|
|
67
67
|
def square_bracket_single argument_index, preshift, return_value, propagation_node
|
68
68
|
original_start_index = preshift.object.begin(argument_index)
|
69
69
|
original_end_index = preshift.object.end(argument_index)
|
70
|
-
original_properties = preshift.object
|
70
|
+
original_properties = Contrast::Agent::Assess::Tracker.properties(preshift.object)
|
71
71
|
applicable_tags = original_properties.tags_at_range(original_start_index...original_end_index)
|
72
72
|
return if applicable_tags.empty?
|
73
73
|
|
74
|
+
return_properties = Contrast::Agent::Assess::Tracker.properties(return_value)
|
74
75
|
applicable_tags.each do |tag_name, tag_ranges|
|
75
|
-
|
76
|
+
return_properties.set_tags(tag_name, tag_ranges)
|
76
77
|
end
|
77
|
-
|
78
|
-
|
78
|
+
original_properties.events.each do |event|
|
79
|
+
return_properties.add_event(event)
|
79
80
|
end
|
80
|
-
return_value.
|
81
|
-
propagation_node, return_value, preshift.object, return_value, preshift.args)
|
81
|
+
return_properties.build_event(propagation_node, return_value, preshift.object, return_value, preshift.args)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -15,23 +15,25 @@ module Contrast
|
|
15
15
|
# String has some silly methods like next. Basically, this flips a
|
16
16
|
# character in a predictable manner
|
17
17
|
def propagate propagation_node, preshift, target
|
18
|
-
|
18
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
19
|
+
return unless properties
|
19
20
|
|
20
|
-
|
21
|
+
source = find_source(propagation_node.sources[0], preshift)
|
22
|
+
properties.copy_from(source, target, 0, propagation_node.untags)
|
21
23
|
|
22
24
|
# this means the char that was shifted overflowed and created new
|
23
25
|
# chars (i.e 'z' "wraps" to create 'aa' )
|
24
26
|
unless target.length == source.length
|
25
|
-
|
27
|
+
properties.copy_from(source, target, 0, propagation_node.untags)
|
26
28
|
|
27
29
|
first_difference = (0...source.length).find { |i| source[i] != target[i] } || source.length
|
28
30
|
|
29
|
-
|
31
|
+
properties.tags_at(first_difference).each do |tag|
|
30
32
|
tag.shift_end(target.length - source.length)
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
|
36
|
+
properties.cleanup_tags
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -14,6 +14,9 @@ module Contrast
|
|
14
14
|
# For the source, prepend its tags to the target. It's basically the
|
15
15
|
# opposite of append. :-P
|
16
16
|
def propagate propagation_node, preshift, target
|
17
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
18
|
+
return unless properties
|
19
|
+
|
17
20
|
sources = propagation_node.sources
|
18
21
|
# source1 is the copy of the thing being prepended to
|
19
22
|
source1 = find_source(sources[0], preshift)
|
@@ -26,25 +29,25 @@ module Contrast
|
|
26
29
|
# tags from the object(since nothing from args was added to
|
27
30
|
# return)
|
28
31
|
if source1.length == target.length
|
29
|
-
|
32
|
+
properties.copy_from(source1, target, 0, propagation_node.untags)
|
30
33
|
else
|
31
34
|
# find original in the target, copy tags to the new position in target
|
32
|
-
|
35
|
+
properties.copy_from(source1, target, original_start_index, propagation_node.untags)
|
33
36
|
# then we add the tags from the thing prepended to the start
|
34
37
|
# of the target
|
35
38
|
start = 0
|
36
39
|
while start < original_start_index
|
37
|
-
|
40
|
+
properties.copy_from(source2, target, start, propagation_node.untags)
|
38
41
|
start += source2.length
|
39
42
|
next unless start > original_start_index
|
40
43
|
|
41
|
-
|
44
|
+
properties.tags_at(start - source2.length).each do |tag|
|
42
45
|
tag.update_end(original_start_index)
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
46
49
|
# and finally merge the tags if any overlap.
|
47
|
-
|
50
|
+
properties.cleanup_tags
|
48
51
|
end
|
49
52
|
end
|
50
53
|
end
|
@@ -17,15 +17,19 @@ module Contrast
|
|
17
17
|
# Once the tag is applied, remove the section that was removed by the delete.
|
18
18
|
# Unlike additive propagation, this currently only supports one source
|
19
19
|
def propagate propagation_node, preshift, target
|
20
|
-
|
21
|
-
|
22
|
-
target.cs__copy_from(source, 0, propagation_node.untags)
|
20
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
21
|
+
return unless properties
|
23
22
|
|
23
|
+
source = find_source(propagation_node.sources[0], preshift)
|
24
|
+
properties.copy_from(source, target, 0, propagation_node.untags)
|
24
25
|
source_chars = source.is_a?(String) ? source.chars : source.string.chars
|
25
26
|
handle_removal(source_chars, target)
|
26
27
|
end
|
27
28
|
|
28
29
|
def handle_removal source_chars, target
|
30
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
31
|
+
return unless properties
|
32
|
+
|
29
33
|
source_idx = 0
|
30
34
|
|
31
35
|
target_chars = target.chars
|
@@ -60,7 +64,7 @@ module Contrast
|
|
60
64
|
remove_ranges << (source_idx...source_chars.length) if source_idx != source_chars.length
|
61
65
|
|
62
66
|
# handle deleting the removed ranges
|
63
|
-
|
67
|
+
properties.delete_tags_at_ranges(remove_ranges)
|
64
68
|
end
|
65
69
|
end
|
66
70
|
end
|
@@ -14,9 +14,12 @@ module Contrast
|
|
14
14
|
# Replace means we're replacing the target w/ the source. Anything
|
15
15
|
# on the source should be passed to the target.
|
16
16
|
def propagate propagation_node, preshift, target
|
17
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
18
|
+
return unless properties
|
19
|
+
|
17
20
|
source = find_source(propagation_node.sources[0], preshift)
|
18
|
-
|
19
|
-
|
21
|
+
properties.clear_tags
|
22
|
+
properties.copy_from(source, target, 0, propagation_node.untags)
|
20
23
|
end
|
21
24
|
end
|
22
25
|
end
|
@@ -13,13 +13,15 @@ module Contrast
|
|
13
13
|
class Reverse < Contrast::Agent::Assess::Policy::Propagator::Base
|
14
14
|
class << self
|
15
15
|
def propagate propagation_node, preshift, target
|
16
|
-
|
16
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
17
|
+
return unless properties
|
17
18
|
|
18
|
-
|
19
|
+
source = find_source(propagation_node.sources[0], preshift)
|
20
|
+
properties.copy_from(source, target, 0, propagation_node.untags)
|
19
21
|
|
20
22
|
length = target.length
|
21
|
-
|
22
|
-
tags =
|
23
|
+
properties.tag_keys.each do |key|
|
24
|
+
tags = properties.fetch_tag(key)
|
23
25
|
tags.each do |tag|
|
24
26
|
new_end = length - tag.start_idx
|
25
27
|
new_start = new_end - tag.length
|
@@ -27,7 +29,7 @@ module Contrast
|
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
|
32
|
+
properties.cleanup_tags
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
@@ -14,6 +14,9 @@ module Contrast
|
|
14
14
|
class Select
|
15
15
|
class << self
|
16
16
|
def select_tagger patcher, preshift, ret, _block
|
17
|
+
properties = Contrast::Agent::Assess::Tracker.properties(ret)
|
18
|
+
return unless properties
|
19
|
+
|
17
20
|
source = preshift.object
|
18
21
|
args = preshift.args
|
19
22
|
|
@@ -21,12 +24,17 @@ module Contrast
|
|
21
24
|
# Additionally, an empty string is returned when the starting index for
|
22
25
|
# a character range is at the end of the string. Let's just skip that
|
23
26
|
# and only track a string that has length
|
24
|
-
|
27
|
+
unless ret &&
|
28
|
+
!ret.empty? &&
|
29
|
+
Contrast::Agent::Assess::Tracker.tracked?(source)
|
30
|
+
return
|
31
|
+
end
|
25
32
|
|
26
|
-
|
27
|
-
|
33
|
+
source_properties = Contrast::Agent::Assess::Tracker.properties(source)
|
34
|
+
source_properties.events.each do |event|
|
35
|
+
properties.events << event
|
28
36
|
end
|
29
|
-
|
37
|
+
properties.build_event(
|
30
38
|
patcher,
|
31
39
|
ret,
|
32
40
|
source,
|
@@ -36,10 +44,10 @@ module Contrast
|
|
36
44
|
range = determine_select_range(source, args)
|
37
45
|
return unless range
|
38
46
|
|
39
|
-
tags =
|
40
|
-
|
47
|
+
tags = source_properties.tags_at_range(range)
|
48
|
+
properties.clear_tags
|
41
49
|
tags.each_pair do |key, value|
|
42
|
-
|
50
|
+
properties.set_tags(key, value)
|
43
51
|
end
|
44
52
|
ret
|
45
53
|
end
|
@@ -17,11 +17,11 @@ module Contrast
|
|
17
17
|
propagation_node.sources.each do |source|
|
18
18
|
case source
|
19
19
|
when Contrast::Utils::ObjectShare::OBJECT_KEY
|
20
|
-
tracked_inputs << preshift.object if preshift.object
|
20
|
+
tracked_inputs << preshift.object if Contrast::Agent::Assess::Tracker.tracked?(preshift.object)
|
21
21
|
else
|
22
22
|
arg = preshift.args[source]
|
23
23
|
if arg.is_a?(String)
|
24
|
-
tracked_inputs << arg if
|
24
|
+
tracked_inputs << arg if Contrast::Agent::Assess::Tracker.tracked?(arg)
|
25
25
|
elsif Contrast::Utils::DuckUtils.iterable_hash?(arg)
|
26
26
|
arg.each_pair do |key, value|
|
27
27
|
tracked_inputs << key if tracked_value?(key)
|
@@ -36,19 +36,25 @@ module Contrast
|
|
36
36
|
end
|
37
37
|
|
38
38
|
splat_tags(tracked_inputs, target)
|
39
|
-
target.
|
39
|
+
Contrast::Agent::Assess::Tracker.properties(target).cleanup_tags
|
40
40
|
end
|
41
41
|
|
42
42
|
def splat_tags tracked_inputs, target
|
43
43
|
return if tracked_inputs.empty?
|
44
44
|
|
45
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
46
|
+
return unless properties
|
47
|
+
|
45
48
|
tracked_inputs.each do |input|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
input_properties = Contrast::Agent::Assess::Tracker.properties(input)
|
50
|
+
next unless input_properties
|
51
|
+
|
52
|
+
properties.splat_from(input, target)
|
53
|
+
next if input == target
|
54
|
+
|
55
|
+
input_properties.events.each do |event|
|
56
|
+
properties.events << event
|
50
57
|
end
|
51
|
-
input.cs__splat_tags(target)
|
52
58
|
end
|
53
59
|
end
|
54
60
|
end
|
@@ -53,17 +53,20 @@ module Contrast
|
|
53
53
|
target.each do |elem|
|
54
54
|
elem_length = elem.length
|
55
55
|
range = current_index...(current_index + elem_length)
|
56
|
-
|
56
|
+
elem_properties = Contrast::Agent::Assess::Tracker.properties(elem)
|
57
|
+
next unless elem_properties
|
57
58
|
|
58
|
-
|
59
|
+
source_properties = Contrast::Agent::Assess::Tracker.properties(source)
|
60
|
+
tags = source_properties.tags_at_range(range)
|
61
|
+
elem_properties.clear_tags
|
59
62
|
tags.each_pair do |key, value|
|
60
|
-
|
63
|
+
elem_properties.set_tags(key, value)
|
61
64
|
end
|
62
|
-
|
63
|
-
|
65
|
+
source_properties.events.each do |event|
|
66
|
+
elem_properties.add_event(event)
|
64
67
|
end
|
65
|
-
|
66
|
-
|
68
|
+
elem_properties.build_event(propagation_node, elem, preshift.object, target, preshift.args, 0)
|
69
|
+
elem_properties.add_properties(propagation_node.properties)
|
67
70
|
current_index = current_index + elem_length + separator_length
|
68
71
|
end
|
69
72
|
nil
|
@@ -125,8 +128,11 @@ module Contrast
|
|
125
128
|
index = SPLIT_TRACKER.get(:split_index)&.fetch(depth)
|
126
129
|
return unless index
|
127
130
|
|
131
|
+
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
132
|
+
return unless properties
|
133
|
+
|
128
134
|
true_source = source[index]
|
129
|
-
|
135
|
+
properties.copy_from(true_source, target)
|
130
136
|
rescue StandardError => e
|
131
137
|
logger.warn('Unable to track within split context', e)
|
132
138
|
ensure
|