class Ronin::Support::Binary::Stack

Represents a stack that can have binary data pushed to or popped from it.

## Features

## Examples

Creating a new stack:

stack = Binary::Stack.new
# => #<Ronin::Support::Binary::Stack: "">
stack.push 0x41414141
# => #<Ronin::Support::Binary::Stack: "AAAA\x00\x00\x00\x00">
stack.push 0x7fffffffdde0
# => #<Ronin::Support::Binary::Stack: "\xE0\xDD\xFF\xFF\xFF\x7F\x00\x00AAAA\x00\x00\x00\x00">
stack.push -1
# => #<Ronin::Support::Binary::Stack: "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\xDD\xFF\xFF\xFF\x7F\x00\x00AAAA\x00\x00\x00\x00">
stack.to_s
# => => "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\xDD\xFF\xFF\xFF\x7F\x00\x00AAAA\x00\x00\x00\x00"

Creating a stack from an existing String:

stack = Binary::Stack.new("\x41\x00\x00\x00\x00\x00\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00")
stack[0]
# => 65
stack[8]
# => 66

Negative indexing within the stack:

stack.push(65)
stack.push(66)
stack[-8]
# => 65
stack[-16]
# => 66

Note: negative indexes are treated relative to the beginning of the stack, since stacks grow downward in the address space.

@api public

@since 1.0.0

Attributes

length[R]

The number of machine words on the stack.

@return [Integer]

machine_word[R]

The “machine word” from the {#type_system}.

@return [CTypes::UInt32Type, CTypes::UInt64Type]

size[R]

The size of the stack in bytes.

@return [Integer]

string[R]

The underlying buffer for the stack.

@return [String]

Public Class Methods

new(string=nil, **kwargs) click to toggle source

Initializes the stack.

@param [String, nil] string

Optional existing stack contents.

@param [Hash{Symbol => Object}] kwargs

Additional keyword arguments.

@option kwargs [:little, :big, :net, nil] :endian

The desired endianness of the values within the stack.

@option kwargs [:x86, :x86_64,

              :ppc, :ppc64,
              :mips, :mips_le, :mips_be,
              :mips64, :mips64_le, :mips64_be,
              :arm, :arm_le, :arm_be,
              :arm64, :arm64_le, :arm64_be] :arch
The desired architecture for the values within the stack.
# File lib/ronin/support/binary/stack.rb, line 118
def initialize(string=nil, **kwargs)
  initialize_type_system(**kwargs)

  @machine_word = @type_system::MACHINE_WORD

  if string
    @string = string
    @size   = @string.bytesize
    @length = @size / @machine_word.size
  else
    @string = String.new
    @size   = 0
    @length = 0
  end
end

Public Instance Methods

[](index) click to toggle source

Accesses a machine word at the given index within the stack.

@param [Integer] index

The byte offset within the stack to read from.

@return [Integer]

The value at the index within the stack.

@raise [IndexError]

@note

negative offsets are treated as relative to the bottom or the
beginning of the stack, since stack grow downward in the address
space.
# File lib/ronin/support/binary/stack.rb, line 150
def [](index)
  offset = if index < 0 then @size + index
           else              index
           end

  if (offset + @machine_word.size) > @size
    raise(IndexError,"index #{index} is out of bounds: 0...#{@size}")
  end

  data = @string[offset,@machine_word.size]
  return @machine_word.unpack(data)
end
[]=(index,value) click to toggle source

Sets a machine word at the given index within the stack.

@param [Integer] index

The byte offset within the stack to write to.

@param [Integer] value

The value to write at the index within the stack.

@return [Integer]

The written value.

@raise [IndexError]

@note

negative offsets are treated as relative to the bottom or the
beginning of the stack, since stacks grow downward in the address
space.
# File lib/ronin/support/binary/stack.rb, line 182
def []=(index,value)
  offset = if index < 0 then @size + index
           else              index
           end

  if (offset + @machine_word.size) > @size
    raise(IndexError,"index #{index} is out of bounds: 0...#{@size}")
  end

  @string[offset,@machine_word.size] = @machine_word.pack(value)
  return value
end
inspect() click to toggle source

Inspects the stack object.

@return [String]

# File lib/ronin/support/binary/stack.rb, line 248
def inspect
  "#<#{self.class}: #{@string.inspect}>"
end
pop() click to toggle source

Pops a value off the top of the stack (or to the end of the underlying buffer).

@return [Integer]

The value popped from the stack.
# File lib/ronin/support/binary/stack.rb, line 220
def pop
  data  = @string.byteslice(0,@machine_word.size)
  value = @machine_word.unpack(data)

  @length -= 1
  @size   -= @machine_word.size

  @string = @string.byteslice(@machine_word.size,@size)
  return value
end
push(value) click to toggle source

Pushes a value onto the top of the stack (or to the end of the underlying buffer).

@param [Integer] value

The value to push onto the stack.

@return [self]

# File lib/ronin/support/binary/stack.rb, line 204
def push(value)
  data = @machine_word.pack(value)

  @string.insert(0,data)
  @length += 1
  @size   += @machine_word.size
  return self
end
to_s() click to toggle source

Cnnverts the stack into a String.

@return [String]

The underlying buffer for the stack.
# File lib/ronin/support/binary/stack.rb, line 237
def to_s
  @string
end
Also aliased as: to_str
to_str()
Alias for: to_s