Class: SvgSentinel::StructureListener

Inherits:
Object
  • Object
show all
Includes:
REXML::StreamListener
Defined in:
lib/svg_sentinel/structure_listener.rb

Overview

A streaming (SAX) listener that bounds the shape of the document - nesting depth, total element count, per-element attribute count - without ever building a DOM. It runs before the tree parser so a pathologically deep or wide payload is refused early, on a memory-bounded pass, instead of being fully materialised. The byte cap limits raw size; this limits the structural cost that a small byte count can still hide (deep nesting, attribute floods).

Defined Under Namespace

Classes: Breach

Constant Summary collapse

LimitExceeded =
Class.new(StandardError)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_depth:, max_nodes:, max_attributes:) ⇒ StructureListener

Returns a new instance of StructureListener.



24
25
26
27
28
29
30
31
# File 'lib/svg_sentinel/structure_listener.rb', line 24

def initialize(max_depth:, max_nodes:, max_attributes:)
  @max_depth = max_depth
  @max_nodes = max_nodes
  @max_attributes = max_attributes
  @depth = 0
  @nodes = 0
  @breach = nil
end

Instance Attribute Details

#breachObject (readonly)

Returns the value of attribute breach.



22
23
24
# File 'lib/svg_sentinel/structure_listener.rb', line 22

def breach
  @breach
end

Instance Method Details

#tag_end(_name) ⇒ Object



48
49
50
# File 'lib/svg_sentinel/structure_listener.rb', line 48

def tag_end(_name)
  @depth -= 1
end

#tag_start(_name, attributes) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/svg_sentinel/structure_listener.rb', line 33

def tag_start(_name, attributes)
  @nodes += 1
  @depth += 1

  if @max_nodes && @nodes > @max_nodes
    breach!(:too_many_nodes, "document has more than #{@max_nodes} elements")
  end
  if @max_depth && @depth > @max_depth
    breach!(:too_deep, "element nesting is deeper than #{@max_depth} levels")
  end
  if @max_attributes && attributes && attributes.size > @max_attributes
    breach!(:too_many_attributes, "an element has more than #{@max_attributes} attributes")
  end
end