Class: Contrast::Agent::Assess::ContrastEvent

Inherits:
Object
  • Object
show all
Includes:
Utils::PreventSerialization
Defined in:
lib/contrast/agent/assess/contrast_event.rb

Overview

This class holds the data about an event in the application We’ll use it to build an event that TeamServer can consume if the object to which this event belongs ends in a trigger.

Direct Known Subclasses

Events::SourceEvent

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils::PreventPsychSerialization

#encode_with, #init_with

Methods included from Utils::PreventMarshalSerialization

#marshal_dump, #marshal_load

Constructor Details

#initialize(policy_node, tagged, object, ret, args) ⇒ ContrastEvent

Returns a new instance of ContrastEvent.

Parameters:

  • policy_node (Contrast::Agent::Assess::Policy::PolicyNode)

    the node that governs this event.

  • tagged (Object)

    the Target to which this event pertains.

  • object (Object)

    the Object on which the method was invoked

  • ret (Object)

    the Return of the invoked method

  • args (Array<Object>)

    the Arguments with which the method was invoked



107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/contrast/agent/assess/contrast_event.rb', line 107

def initialize policy_node, tagged, object, ret, args
  @policy_node = policy_node
  # so long as this event is built in a factory, we know Contrast Code
  # will be the first three events
  @stack_trace = caller(3, 20)
  @time = Contrast::Utils::Timer.now_ms
  @thread = Thread.current.object_id

  # These methods rely on the above being set. Don't move them!
  @event_id = Contrast::Agent::Assess::ContrastEvent.next_atomic_id
  find_parent_events!(policy_node, object, ret, args)
  snapshot!(tagged, object, ret, args)
end

Instance Attribute Details

#argsArray<Object> (readonly)

the safe representation of the Arguments with which the method was invoked

Returns:

  • (Array<Object>)

    the current value of args



35
36
37
# File 'lib/contrast/agent/assess/contrast_event.rb', line 35

def args
  @args
end

#event_idInteger (readonly)

the atomic id of this event

Returns:

  • (Integer)

    the current value of event_id



35
36
37
# File 'lib/contrast/agent/assess/contrast_event.rb', line 35

def event_id
  @event_id
end

#objectString (readonly)

the safe representation of the Object on which the method was invoked

Returns:

  • (String)

    the current value of object



35
36
37
# File 'lib/contrast/agent/assess/contrast_event.rb', line 35

def object
  @object
end

#policy_nodeContrast::Agent::Assess::Policy::PolicyNode (readonly)

the node that governs this event.

Returns:



35
36
37
# File 'lib/contrast/agent/assess/contrast_event.rb', line 35

def policy_node
  @policy_node
end

#retString (readonly)

the safe representation of the Return of the invoked method

Returns:

  • (String)

    the current value of ret



35
36
37
# File 'lib/contrast/agent/assess/contrast_event.rb', line 35

def ret
  @ret
end

#stack_traceArray<String> (readonly)

the execution stack at the time the method for this event was invoked

Returns:

  • (Array<String>)

    the current value of stack_trace



35
36
37
# File 'lib/contrast/agent/assess/contrast_event.rb', line 35

def stack_trace
  @stack_trace
end

#threadInteger (readonly)

the object id of the thread on which this event was generated

Returns:

  • (Integer)

    the current value of thread



35
36
37
# File 'lib/contrast/agent/assess/contrast_event.rb', line 35

def thread
  @thread
end

#timeInteger (readonly)

the time, in epoch ms, when this event was created

Returns:

  • (Integer)

    the current value of time



35
36
37
# File 'lib/contrast/agent/assess/contrast_event.rb', line 35

def time
  @time
end

Class Method Details

.next_atomic_idObject



91
92
93
94
95
96
97
98
# File 'lib/contrast/agent/assess/contrast_event.rb', line 91

def self.next_atomic_id
  @atomic_mutex.synchronize do
    @atomic_id += 1
    # Rollover things
  rescue StandardError
    @atomic_id = 1
  end
end

.safe_args_representation(args) ⇒ Array<String>

Given an array of arguments, copy them into a safe, meaning String, format that we can use to send to SR and TS for rendering.

Parameters:

  • args (Array<Object>)

    the arguments to translate

Returns:

  • (Array<String>)

    the String forms of those Objects, as determined by Contrast::Utils::ClassUtil.to_contrast_string



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/contrast/agent/assess/contrast_event.rb', line 45

def safe_args_representation args
  return nil unless args
  return Contrast::Utils::ObjectShare::EMPTY_ARRAY if args.empty?

  rep = []
  args.each do |arg|
    # We have to handle named args
    rep <<  if arg.is_a?(Hash)
              safe_arg_hash_representation(arg)
            else
              Contrast::Utils::ClassUtil.to_contrast_string(arg)
            end
  end
  rep
end

.safe_dup(original) ⇒ Object?

if given an object that can be duped, duplicate it. otherwise just return the original object. swallow all exceptions from non-duplicable things.

we can’t just check respond_to? though b/c dup exists on the base Object class

Parameters:

  • original (Object, nil)

    the thing to duplicate

Returns:

  • (Object, nil)

    a copy of that thing



70
71
72
73
74
# File 'lib/contrast/agent/assess/contrast_event.rb', line 70

def safe_dup original
  return nil unless original

  Contrast::Agent::Assess::Tracker.duplicate(original)
end

Instance Method Details

#determine_taint_target(event_dtm) ⇒ Object

We have to do a little work to figure out what our TS appropriate target is. To break this down, the logic is as follows: 1) If my policy_node has a target, work on targets. Else, work on sources.

Per TS law, each policy_node must have at least a source or a target.
The only type of policy_node w/o targets is a Trigger, but that may
change.

2) If I have a highlight, it means that I have a P target that is

not in integer form (it was a named / keyword type for which I had
to find the index). I need to address this so that TS can process
it.

3) I’ll set the event’s source and target to TS values. 4) Return the highlight or the first source/target as the taint

target.


138
139
140
141
142
143
144
145
146
147
148
# File 'lib/contrast/agent/assess/contrast_event.rb', line 138

def determine_taint_target event_dtm
  if @policy_node&.targets&.any?
    event_dtm.source = @policy_node.source_string if @policy_node.source_string
    event_dtm.target = @highlight ? "P#{ @highlight }" : @policy_node.target_string
    @highlight || @policy_node.targets[0]
  elsif policy_node&.sources&.any?
    event_dtm.source = @highlight ? "P#{ @highlight }" : @policy_node.source_string
    event_dtm.target = @policy_node.target_string if @policy_node.target_string
    @highlight || @policy_node.sources[0]
  end
end

#parent_eventsObject



121
122
123
# File 'lib/contrast/agent/assess/contrast_event.rb', line 121

def parent_events
  @_parent_events ||= []
end

#to_dtm_eventObject

Convert this event into a DTM that TeamServer can consume



151
152
153
# File 'lib/contrast/agent/assess/contrast_event.rb', line 151

def to_dtm_event
  Contrast::Api::Dtm::TraceEvent.build(self)
end