lens_of_truth 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT +9 -0
- data/LICENSE +13 -0
- data/README.md +60 -0
- data/Rakefile +7 -0
- data/lens_of_truth.gemspec +17 -0
- data/lib/lens_of_truth/core_ext.rb +3 -0
- data/lib/lens_of_truth/version.rb +3 -0
- data/lib/lens_of_truth.rb +25 -0
- data/spec/lens_of_truth_spec.rb +49 -0
- metadata +53 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: c683afe773d926b884d995ae7ff5bc05fec12f11
|
|
4
|
+
data.tar.gz: 289b22fef2d14618f33c9f9e75414d47f8dbca9c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0ed81aaf5eedbb77795e96d087d0539f38e030d501d866c65d606454a1b79bf073fe6d196989731c31c8e22f10012b5c2fa2d0ea03a315ab49243f587d2db21a
|
|
7
|
+
data.tar.gz: 2231dc06fd3cfb5efafdb4d7f94c5f3b97d08193b8bea926c74efbd797d5a82969f603ce7d4225961d3fb1c5e6bffb909ac97f1e5798665dca9a0950b7600803
|
data/CODE_OF_CONDUCT
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
,---. ,---.-./`) ,---. .--. ____ .-'''-. .--. .--. ____ ,---. .--.
|
|
2
|
+
| \ / \ .-.')| \ | | .' __ `. / _ \| |_ | | .' __ `.| \ | |
|
|
3
|
+
| , \/ , / `-' \| , \ | |/ ' \ \ (`' )/`--'| _( )_ | |/ ' \ \ , \ | |
|
|
4
|
+
| |\_ /| |`-'`"`| |\_ \| ||___| / |(_ o _). |(_ o _) | ||___| / | |\_ \| |
|
|
5
|
+
| _( )_/ | |.---. | _( )_\ | _.-` | (_,_). '. | (_,_) \ | | _.-` | _( )_\ |
|
|
6
|
+
| (_ o _) | || | | (_ o _) |.' _ |.---. \ :| |/ \| |.' _ | (_ o _) |
|
|
7
|
+
| (_,_) | || | | (_,_)\ || _( )_ |\ `-' || ' /\ ` || _( )_ | (_,_)\ |
|
|
8
|
+
| | | || | | | | |\ (_ o _) / \ / | / \ |\ (_ o _) / | | |
|
|
9
|
+
'--' '--''---' '--' '--' '.(_,_).' `-...-' `---' `---` '.(_,_).''--' '--'
|
data/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
2
|
+
Version 2, December 2004
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
|
5
|
+
|
|
6
|
+
Everyone is permitted to copy and distribute verbatim or modified
|
|
7
|
+
copies of this license document, and changing it is allowed as long
|
|
8
|
+
as the name is changed.
|
|
9
|
+
|
|
10
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
11
|
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION, AND MODIFICATION
|
|
12
|
+
|
|
13
|
+
0. You just DO WHAT THE FUCK YOU WANT TO.
|
data/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#  Lens of Truth
|
|
2
|
+
|
|
3
|
+
**lens_of_truth**, like [its namesake](http://zeldawiki.org/Lens_of_Truth), lets you find things the developers hid from you.
|
|
4
|
+
|
|
5
|
+
Operating on the assumption that related data tend to live reasonably close together in memory, `Object#find_nearby` looks up and down the heap from the receiver's address in search of an object which meets some specification.
|
|
6
|
+
|
|
7
|
+
### "Use cases"
|
|
8
|
+
|
|
9
|
+
Under the hood, `Enumerator` is implemented in terms of fibers so as to support suspension and resumption. CRuby does the right thing by not exposing this implementation detail directly, but maybe we want a reference to the underlying `Fiber` anyway. We knows its [approximate location](https://git.io/vzNsN), so let's see if the **Lens of Truth** can help us home in on it:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
require 'fiber' # for Fiber#transfer
|
|
13
|
+
require 'lens_of_truth'
|
|
14
|
+
|
|
15
|
+
using LensOfTruth # refinement
|
|
16
|
+
|
|
17
|
+
enum = Enumerator.new { |y|
|
|
18
|
+
y << y.find_nearby(Fiber) << 42
|
|
19
|
+
}
|
|
20
|
+
enum.next.transfer
|
|
21
|
+
enum.next # => cannot resume transferred Fiber (FiberError)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Another extremely practical use for the Lens is to peek into the internals of lazy sequences.
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
[].lazy.map(&:succ).take(10)
|
|
28
|
+
# => #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: []>:map>:take(10)>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Instances of `Enumerator::Lazy` clearly know their history, but they've hitherto been pretty hush-hush about it. In CRuby at least, they store [their method and arguments](https://git.io/vzN8H) in hidden instance variables (ones with no leading asperand and which are thus inaccessible from Ruby land). No matter: since an object's [instance variable table](https://git.io/vzNlq) is in the vicinity of the object itself, the **Lens of Truth** can help us find our way:
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
require 'lens_of_truth/core_ext' # patch Object directly
|
|
35
|
+
|
|
36
|
+
seq = [].lazy
|
|
37
|
+
seq = seq.map(&:succ)
|
|
38
|
+
seq.find_nearby(Proc).call(41) # => 42
|
|
39
|
+
seq = seq.take(10)
|
|
40
|
+
seq.find_nearby(Array) # => [10]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Finding the right `Proc` or `Array` is a little harder (read: non-deterministic) since there are usually a lot of them about, but 60% of the time, it works every time.
|
|
44
|
+
|
|
45
|
+
### Usage
|
|
46
|
+
|
|
47
|
+
`Object#find_nearby` uses case equality (`===`) when performing the search, so you can scan around for nearby strings matching some regular expression or a numeric object within a given range. You can instead pass a block to be used as the predicate. There's also an optional keyword argument `limit` which specifies how far to search in other direction before bailing. Examples follow.
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
p Object.find_nearby /^[A-Z]+$/
|
|
51
|
+
# => "DESTDIR"
|
|
52
|
+
p LensOfTruth.find_nearby 42..1337, limit: 9001
|
|
53
|
+
# => nil :(
|
|
54
|
+
p find_nearby { |o| o.is_a?(Hash) && o.size == 1 }
|
|
55
|
+
# => {:frozen_string_literal=>false} :)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Contributing
|
|
59
|
+
|
|
60
|
+
Interesting use cases welcome.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
$:.unshift File.expand_path '../lib', __FILE__
|
|
2
|
+
require 'lens_of_truth/version'
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |s|
|
|
5
|
+
s.name = 'lens_of_truth'
|
|
6
|
+
s.version = LensOfTruth::VERSION
|
|
7
|
+
s.author = 'D.E. Akers'
|
|
8
|
+
s.email = '0x0dea@gmail.com'
|
|
9
|
+
|
|
10
|
+
s.summary = 'Use the Lens of Truth to find objects hidden nearby.'
|
|
11
|
+
s.description = 'lens_of_truth adds Object#find_nearby to look around in proximal memory for things of interest.'
|
|
12
|
+
|
|
13
|
+
s.homepage = 'https://github.com/0x0dea/lens_of_truth'
|
|
14
|
+
s.license = 'WTFPL'
|
|
15
|
+
|
|
16
|
+
s.files = `git ls-files`.split
|
|
17
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'fiddle'
|
|
2
|
+
|
|
3
|
+
module LensOfTruth
|
|
4
|
+
def find_nearby spec = Object, limit: Float::INFINITY
|
|
5
|
+
spec = proc if block_given?
|
|
6
|
+
found = nil
|
|
7
|
+
swivel = Fiddle::SIZEOF_UINTPTR_T / 2
|
|
8
|
+
|
|
9
|
+
[-swivel, swivel].map { |coef|
|
|
10
|
+
Thread.new do |i = 0|
|
|
11
|
+
until found || i > limit
|
|
12
|
+
begin
|
|
13
|
+
obj = ObjectSpace._id2ref __id__ + coef * i += 1
|
|
14
|
+
break found = obj if spec === obj
|
|
15
|
+
rescue RangeError
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
}.each &:join
|
|
20
|
+
|
|
21
|
+
found
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
refine(Object) { include LensOfTruth }
|
|
25
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'minitest/autorun'
|
|
2
|
+
require 'minitest/pride'
|
|
3
|
+
require 'lens_of_truth'
|
|
4
|
+
|
|
5
|
+
using LensOfTruth
|
|
6
|
+
|
|
7
|
+
describe 'Object#find_nearby' do
|
|
8
|
+
|
|
9
|
+
it "should be able to find an Enumerator's underlying Fiber" do
|
|
10
|
+
require 'fiber'
|
|
11
|
+
|
|
12
|
+
enum = Enumerator.new { |y| y << y.find_nearby(Fiber) << 42 }
|
|
13
|
+
enum.next.transfer
|
|
14
|
+
|
|
15
|
+
e = -> { enum.next }.must_raise FiberError
|
|
16
|
+
e.message.must_match 'cannot resume transferred Fiber'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should be able to find a singleton class's attachee" do
|
|
20
|
+
obj = Object.new
|
|
21
|
+
cls = obj.singleton_class
|
|
22
|
+
|
|
23
|
+
cls.find_nearby { |o|
|
|
24
|
+
o.singleton_class == cls rescue nil
|
|
25
|
+
}.must_be_same_as obj
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# NOTE: These next two are kinda flaky.
|
|
29
|
+
|
|
30
|
+
it "should be able to grab a lazy sequence's method" do
|
|
31
|
+
seq = [].lazy
|
|
32
|
+
|
|
33
|
+
foo = proc {} # Sprinkle the stack
|
|
34
|
+
seq = seq.map &:succ
|
|
35
|
+
bar = proc {} # for confusion.
|
|
36
|
+
|
|
37
|
+
seq.find_nearby(Proc).call(41).must_equal 42
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should be able to grab a lazy sequence's arguments" do
|
|
41
|
+
seq = [].lazy
|
|
42
|
+
|
|
43
|
+
foo = [1,2,3] # More
|
|
44
|
+
seq = seq.take 10
|
|
45
|
+
bar = [4,5,6] # sprinkles.
|
|
46
|
+
|
|
47
|
+
seq.find_nearby(Array).must_equal [10]
|
|
48
|
+
end
|
|
49
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lens_of_truth
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- D.E. Akers
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-01-29 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: lens_of_truth adds Object#find_nearby to look around in proximal memory
|
|
14
|
+
for things of interest.
|
|
15
|
+
email: 0x0dea@gmail.com
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- CODE_OF_CONDUCT
|
|
21
|
+
- LICENSE
|
|
22
|
+
- README.md
|
|
23
|
+
- Rakefile
|
|
24
|
+
- lens_of_truth.gemspec
|
|
25
|
+
- lib/lens_of_truth.rb
|
|
26
|
+
- lib/lens_of_truth/core_ext.rb
|
|
27
|
+
- lib/lens_of_truth/version.rb
|
|
28
|
+
- spec/lens_of_truth_spec.rb
|
|
29
|
+
homepage: https://github.com/0x0dea/lens_of_truth
|
|
30
|
+
licenses:
|
|
31
|
+
- WTFPL
|
|
32
|
+
metadata: {}
|
|
33
|
+
post_install_message:
|
|
34
|
+
rdoc_options: []
|
|
35
|
+
require_paths:
|
|
36
|
+
- lib
|
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - ">="
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
requirements: []
|
|
48
|
+
rubyforge_project:
|
|
49
|
+
rubygems_version: 2.5.1
|
|
50
|
+
signing_key:
|
|
51
|
+
specification_version: 4
|
|
52
|
+
summary: Use the Lens of Truth to find objects hidden nearby.
|
|
53
|
+
test_files: []
|