Class: Rex::Poly::LogicalBlock
- Inherits:
-
Object
- Object
- Rex::Poly::LogicalBlock
- Defined in:
- lib/rex/poly/block.rb
Overview
This class represents a logical block which is defined as a concise portion of code that may have one or more functionally equivalent implementations. A logical block should serve a very specific purpose, and any permutations beyond the first should result in exactly the same functionality without any adverse side effects to other blocks.
Like blocks of code, LogicalBlock’s can depend on one another in terms of ordering and precedence. By marking blocks as dependent on another, a hierarchy begins to form. This is a block dependency graph.
To add permutations to a LogicalBlock, they can either be passed in as a list of arguments to the constructor following the blocks name or can be added on the fly by calling the add_perm method. To get a random permutation, the rand_perm method can be called.
To mark one block as depending on another, the depends_on method can be called with zero or more LogicalBlock instances as parameters.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#generated ⇒ Object
Whether or not this block has currently been generated for a given iteration.
-
#offset ⇒ Object
This attributes contains the currently assigned offset of the permutation associated with this block into the polymorphic buffer that is being generated.
Instance Method Summary collapse
-
#add_perm(*perms) ⇒ Object
Adds zero or more specific permutations that may be represented either as strings or as Proc’s to be called at evaluation time.
-
#clobbers(*registers) ⇒ Object
Defines the list of zero or more LogicalRegister’s that this block clobbers.
-
#depends_on(*depends) ⇒ Object
Sets the blocks that this block instance depends on.
-
#deref ⇒ Object
Increments the number of blocks that have completed their dependency pass on this block.
-
#each_clobbers(&block) ⇒ Object
Enumerates each register instance that is clobbered by this block.
-
#generate(save_registers = nil, state = nil, badchars = nil) ⇒ Object
Generates the polymorphic buffer that results from this block and any of the blocks that it either directly or indirectly depends on.
-
#initialize(name, *perms) ⇒ LogicalBlock
constructor
Initializes the logical block’s name along with zero or more specific blocks.
-
#last_reference? ⇒ Boolean
Returns true if there is only one block reference remaining.
-
#name ⇒ Object
Returns the block’s name.
-
#next_blocks(*blocks) ⇒ Object
Defines the next blocks, but not in a dependency fashion but rather in a linking of separate block contexts.
-
#offset_of(lblock) ⇒ Object
Returns the offset of a block.
-
#once ⇒ Object
Returns true if this block is a ‘once’ block.
-
#once=(tf) ⇒ Object
Flags whether or not the block should only be generated once.
-
#rand_perm ⇒ Object
Returns a random permutation that is encapsulated in a Permutation class instance.
-
#rand_perm_badchars ⇒ Object
Returns a random permutation that passes any necessary bad character checks.
-
#ref ⇒ Object
Increments the number of blocks that depend on this block.
-
#regnum_of(reg) ⇒ Object
Returns the register number associated with the supplied LogicalRegister instance.
-
#reset ⇒ Object
Resets the block back to its starting point.
- #size_of(lblock) ⇒ Object
Constructor Details
#initialize(name, *perms) ⇒ LogicalBlock
Initializes the logical block’s name along with zero or more specific blocks.
76 77 78 79 80 81 82 |
# File 'lib/rex/poly/block.rb', line 76 def initialize(name, *perms) @name = name reset add_perm(*perms) end |
Instance Attribute Details
#generated ⇒ Object
Whether or not this block has currently been generated for a given iteration.
315 316 317 |
# File 'lib/rex/poly/block.rb', line 315 def generated @generated end |
#offset ⇒ Object
This attributes contains the currently assigned offset of the permutation associated with this block into the polymorphic buffer that is being generated.
309 310 311 |
# File 'lib/rex/poly/block.rb', line 309 def offset @offset end |
Instance Method Details
#add_perm(*perms) ⇒ Object
Adds zero or more specific permutations that may be represented either as strings or as Proc’s to be called at evaluation time.
153 154 155 |
# File 'lib/rex/poly/block.rb', line 153 def add_perm(*perms) @perms.concat(perms) end |
#clobbers(*registers) ⇒ Object
Defines the list of zero or more LogicalRegister’s that this block clobbers.
220 221 222 |
# File 'lib/rex/poly/block.rb', line 220 def clobbers(*registers) @clobbers = registers end |
#depends_on(*depends) ⇒ Object
Sets the blocks that this block instance depends on.
201 202 203 204 205 206 |
# File 'lib/rex/poly/block.rb', line 201 def depends_on(*depends) @depends = depends.dup # Increment dependent references @depends.each { |b| b.ref } end |
#deref ⇒ Object
Increments the number of blocks that have completed their dependency pass on this block. This number should never become higher than the ‘@references` attribute.
138 139 140 |
# File 'lib/rex/poly/block.rb', line 138 def deref @used_references += 1 end |
#each_clobbers(&block) ⇒ Object
Enumerates each register instance that is clobbered by this block.
227 228 229 |
# File 'lib/rex/poly/block.rb', line 227 def each_clobbers(&block) @clobbers.each(&block) end |
#generate(save_registers = nil, state = nil, badchars = nil) ⇒ Object
Generates the polymorphic buffer that results from this block and any of the blocks that it either directly or indirectly depends on. A list of register numbers to be saved can be passed in as an argument.
This method is not thread safe. To call this method on a single block instance from within multiple threads, be sure to encapsulate the calls inside a locked context.
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/rex/poly/block.rb', line 240 def generate(save_registers = nil, state = nil, badchars = nil) # Create a localized state instance if one was not supplied. state = Rex::Poly::State.new if (state == nil) buf = nil cnt = 0 # This is a lame way of doing this. We just try to generate at most 128 # times until we don't have badchars. The reason we have to do it this # way is because of the fact that badchars can be introduced through # block offsetting and register number selection which can't be readily # predicted or detected during the generation phase. In the future we # can make this better, but for now this will have to do. begin buf = do_generate(save_registers, state, badchars) if (buf and (badchars.nil? or Rex::Text.badchar_index(buf, badchars).nil?)) break end end while ((cnt += 1) < 128) # If we passed 128 tries, then we can't succeed. buf = nil if (cnt >= 128) buf end |
#last_reference? ⇒ Boolean
Returns true if there is only one block reference remaining.
145 146 147 |
# File 'lib/rex/poly/block.rb', line 145 def last_reference? (@references - @used_references <= 0) end |
#name ⇒ Object
Returns the block’s name.
103 104 105 |
# File 'lib/rex/poly/block.rb', line 103 def name @name end |
#next_blocks(*blocks) ⇒ Object
Defines the next blocks, but not in a dependency fashion but rather in a linking of separate block contexts.
212 213 214 |
# File 'lib/rex/poly/block.rb', line 212 def next_blocks(*blocks) @next_blocks = blocks.dup end |
#offset_of(lblock) ⇒ Object
Returns the offset of a block. If the active state for this instance is operating in the first phase, then zero is always returned. Otherwise, the correct offset for the supplied block is returned.
272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/rex/poly/block.rb', line 272 def offset_of(lblock) if (@state.first_phase) 0 else if (lblock.kind_of?(SymbolicBlock::End)) @state.curr_offset else lblock.offset end end end |
#once ⇒ Object
Returns true if this block is a ‘once’ block. That is, this block is dependend upon by multiple blocks but should only be generated once.
120 121 122 |
# File 'lib/rex/poly/block.rb', line 120 def once @once end |
#once=(tf) ⇒ Object
Flags whether or not the block should only be generated once. This can be used to mark a blog as being depended upon by multiple blocks, but making it such that it is only generated once.
112 113 114 |
# File 'lib/rex/poly/block.rb', line 112 def once=(tf) @once = tf end |
#rand_perm ⇒ Object
Returns a random permutation that is encapsulated in a Permutation class instance.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/rex/poly/block.rb', line 161 def rand_perm perm = nil if (@state.badchars) perm = rand_perm_badchars else perm = Permutation.new(@perms[rand(@perms.length)], self) end if (perm.nil?) raise RuntimeError, "Failed to locate a valid permutation." end perm end |
#rand_perm_badchars ⇒ Object
Returns a random permutation that passes any necessary bad character checks.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/rex/poly/block.rb', line 181 def rand_perm_badchars idx = rand(@perms.length) off = 0 while (off < @perms.length) p = @perms[(idx + off) % @perms.length] if (p.kind_of?(Proc) or @state.badchars.nil? or Rex::Text.badchar_index(p, @state.badchars).nil?) return Permutation.new(p, self) end off += 1 end end |
#ref ⇒ Object
Increments the number of blocks that depend on this block.
128 129 130 |
# File 'lib/rex/poly/block.rb', line 128 def ref @references += 1 end |
#regnum_of(reg) ⇒ Object
Returns the register number associated with the supplied LogicalRegister instance. If the active state for this instance is operating in the first phase, then zero is always returned. Otherwise, the correct register number is returned based on what is currently assigned to the supplied LogicalRegister instance, if anything.
291 292 293 |
# File 'lib/rex/poly/block.rb', line 291 def regnum_of(reg) (@state.first_phase) ? 0 : reg.regnum end |
#reset ⇒ Object
Resets the block back to its starting point.
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/rex/poly/block.rb', line 87 def reset @perms = [] @depends = [] @next_blocks = [] @clobbers = [] @offset = nil @state = nil @once = false @references = 0 @used_references = 0 @generated = false end |
#size_of(lblock) ⇒ Object
295 296 297 298 299 300 301 302 |
# File 'lib/rex/poly/block.rb', line 295 def size_of(lblock) @state.block_list.map { |b, p| if b == lblock return p.length end } 0 end |