Module: MemoryIO::Util

Defined in:
lib/memory_io/util.rb

Overview

Defines utility methods.

Defined Under Namespace

Classes: FilePermission

Class Method Summary collapse

Class Method Details

.file_permission(file) ⇒ MemoryIO::Util::FilePermission?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns nil is returned if file does not exist or is inaccessible.

Parameters:

  • file (String)

    File name.

Returns:



68
69
70
71
72
# File 'lib/memory_io/util.rb', line 68

def file_permission(file)
  return nil unless File.file?(file)

  FilePermission.new(file)
end

.pack(val, b, endian = :little) ⇒ String

Pack an integer into b bytes.

Examples:

Util.pack(0x123, 4)
#=> "\x23\x01\x00\x00"
Util.pack(0x123, 4, :big)
#=> "\x00\x00\x01\x23"

Parameters:

  • val (Integer)

    The integer to pack. If val contains more than b bytes, only lower b bytes in val will be packed.

  • b (Integer)
  • endian (:little, :big) (defaults to: :little)

    Byte order to pack val in.

Returns:

  • (String)

    Packing result with length b.



163
164
165
166
167
# File 'lib/memory_io/util.rb', line 163

def pack(val, b, endian = :little)
  bytes = Array.new(b) { |i| (val >> (i * 8)) & 0xff }
  bytes.reverse! if endian == :big
  bytes.pack('C*')
end

.read_exactly(stream, size) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Read exactly size bytes from stream.

Examples:

Util.read_exactly(StringIO.new('1234'), 8)
# EOFError: Requires 0x8 bytes, but only 0x4 bytes remain

Parameters:

  • stream (#read)

    Stream to read.

  • size (Integer)

    Number of bytes to read.

Returns:

  • (String)

    The bytes read.

Raises:

  • (EOFError)

    Fewer than size bytes remain in stream.



114
115
116
117
118
119
120
# File 'lib/memory_io/util.rb', line 114

def read_exactly(stream, size)
  str = stream.read(size)
  remain = str.nil? ? 0 : str.size
  raise ::EOFError, format('Requires 0x%x bytes, but only 0x%x bytes remain', size, remain) if remain < size

  str
end

.safe_eval(str, **vars) ⇒ Integer?

Evaluate string safely.

Examples:

Util.safe_eval('heap + 0x10 * pp', heap: 0xde00, pp: 8)
#=> 56960 # 0xde80

Util.safe_eval('0xzz')
#=> nil

Parameters:

  • str (String)

    String to be evaluated.

  • vars ({Symbol => Integer})

    Predefined variables

Returns:

  • (Integer?)

    Result, or nil if str is not a valid expression.



90
91
92
93
94
# File 'lib/memory_io/util.rb', line 90

def safe_eval(str, **vars)
  return str if str.is_a?(Integer)

  Dentaku::Calculator.new.store(vars).evaluate(str)
end

.trim_libname(name) ⇒ String

Remove extension name (.so) and version in library name.

Examples:

Util.trim_libname('libc-2.24.so')
#=> 'libc'
Util.trim_libname('libcrypto.so.1.0.0')
#=> 'libcrypto'
Util.trim_libname('not_a_so')
#=> 'not_a_so'
Util.trim_libname('ld-linux-x86-64.so.2')
#=> 'ld'

Parameters:

  • name (String)

    Original library filename.

Returns:

  • (String)

    Name without version and '.so'.



186
187
188
189
190
191
192
# File 'lib/memory_io/util.rb', line 186

def trim_libname(name)
  return 'ld' if name.start_with?('ld-')

  type1 = '(-[\d.]+)?\.so$'
  type2 = '\.so.[\.\d]+$'
  name.sub(/#{type1}|#{type2}/, '')
end

.underscore(str) ⇒ String

Convert input into snake-case.

This method also converts '::' to '/'.

Examples:

Util.underscore('MemoryIO')
#=> 'memory_io'

Util.underscore('MyModule::MyClass')
#=> 'my_module/my_class'

Parameters:

  • str (String)

    String to be converted.

Returns:

  • (String)

    Converted string.



51
52
53
54
55
56
57
58
59
# File 'lib/memory_io/util.rb', line 51

def underscore(str)
  return '' if str.empty?

  str = str.gsub('::', '/')
  str.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
  str.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
  str.downcase!
  str
end

.unpack(str, endian = :little) ⇒ Integer

Unpack a string into an integer.

Examples:

Util.unpack("\xff")
#=> 255
Util.unpack("@\xE2\x01\x00")
#=> 123456
Util.unpack("\x00\x01\xE2@", :big)
#=> 123456

Parameters:

  • str (String)

    String.

  • endian (:little, :big) (defaults to: :little)

    Byte order of str.

Returns:

  • (Integer)

    Result.



139
140
141
142
# File 'lib/memory_io/util.rb', line 139

def unpack(str, endian = :little)
  bytes = endian == :little ? str.bytes.reverse : str.bytes
  bytes.reduce(0) { |s, c| (s * 256) + c }
end