I've been reading the following blog post , and it's unclear to me why is the author calling eval twice. Wouldn't calling eval just once suffice?
His controller code is this:
class GameController < ApplicationController
def index
end
def handle_command
command = params[:command].split
c = CommandHandler.new
begin
#result = c.send(*command)
rescue Exception =>; e
#result = "Stop being an idiot, and do something useful!"
end
end
end
And example code execution exploits were like this:
eval eval('puts^"Hello^world!"'.gsub('^',('^'.ord-62).chr))
The thing I don't understand is why there is a need for 2 evals, running this in irb, already prints the string by the first eval, and the second eval tries to evaluate nil.
The application is using send to evaluate the function with its arguments. Since eval only expects a single argument, there cannot be any spaces in the second argument. In short, the expression with double evals is executed as:
c.send("eval", "eval('puts^"Hello^world!\"'.gsub('^',('^'.ord-62).chr)"
That is equivalent to:
c.eval "eval('puts^"Hello^world!\"'.gsub('^',('^'.ord-62).chr)"
Which in turn will do the same thing as:
eval('puts^"Hello^world!\"'.gsub('^',('^'.ord-62).chr)
which is:
eval('puts "Hello world!"') #=> Code is actually evaluating
With a single eval you would get:
#input
eval 'puts^"Hello^world!"'.gsub('^',('^'.ord-62).chr)
c.send("eval" "'puts^\"Hello^world!\"'.gsub('^',('^'.ord-62).chr)"
c.eval "'puts^\"Hello^world!\"'.gsub('^',('^'.ord-62).chr)"
#=> "puts \"Hello world!\""
#=> results in a string containing the code. Code is not executed.
Related
I was trying to DRY up a Rails controller by extracting a method that includes a guard clause to return prematurely from the controller method in the event of an error. I thought this may be possible using a to_proc, like this pure Ruby snippet:
def foo(string)
processed = method(:breaker).to_proc.call(string)
puts "This step should not be executed in the event of an error"
processed
end
def breaker(string)
begin
string.upcase!
rescue
puts "Well you messed that up, didn't you?"
return
end
string
end
My thinking was that having called to_proc on the breaker method, calling the early return statement in the rescue clause should escape the execution of foo. However, it didn't work:
2.4.0 :033 > foo('bar')
This step should not be executed in the event of an error
=> "BAR"
2.4.0 :034 > foo(2)
Well you messed that up, didn't you?
This step should not be executed in the event of an error
=> nil
Can anyone please
Explain why this doesn't work
Suggest a way of achieving this effect?
Thanks in advance.
EDIT: as people are wondering why the hell I would want to do this, the context is that I'm trying to DRY up the create and update methods in a Rails controller. (I'm trying to be agressive about it as both methods are about 60 LoC. Yuck.) Both methods feature a block like this:
some_var = nil
if (some complicated condition)
# do some stuff
some_var = computed_value
elsif (some marginally less complicated condition)
#error_msg = 'This message is the same in both actions.'
render partial: "show_user_the_error" and return
# rest of controller actions ...
Hence, I wanted to extract this as a block, including the premature return from the controller action. I thought this might be achievable using a Proc, and when that didn't work I wanted to understand why (which I now do thanks to Marek Lipa).
What about
def foo(string)
processed = breaker(string)
puts "This step should not be executed in the event of an error"
processed
rescue ArgumentError
end
def breaker(string)
begin
string.upcase!
rescue
puts "Well you messed that up, didn't you?"
raise ArgumentError.new("could not call upcase! on #{string.inspect}")
end
string
end
After all this is arguably a pretty good use case for an exception.
It seems part of the confusion is that a Proc or lambda for that matter are distinctly different than a closure (block).
Even if you could convert Method#to_proc to a standard Proc e.g. Proc.new this would simply result in a LocalJumpError because the return would be invalid in this context.
You can use next to break out of a standard Proc but the result would be identical to the lambda that you have now.
The reason Method#to_proc returns a lambda is because a lambda is far more representative of a method call than a standard Proc
For Example:
def foo(string)
string
end
bar = ->(string) { string } #lambda
baz = Proc.new {|string| string }
foo
#=> ArgumentError: wrong number of arguments (given 0, expected 1)
bar.()
#=> ArgumentError: wrong number of arguments (given 0, expected 1)
baz.()
#=> nil
Since you are converting a method to a proc object I am not sure why you would also want the behavior to change as this could cause ambiguity and confusion. Please note that for this reason you can not go in the other direction either e.g. lambda(&baz) does not result in a lambda either as metioned Here.
Now that we have explained all of this and why it shouldn't really be done, it is time to remember that nothing is impossible in ruby so this would technically work:
def foo(string)
# place assignment in the guard clause
# because the empty return will result in `nil` a falsey value
return unless processed = method(:breaker).to_proc.call(string)
puts "This step should not be executed in the event of an error"
processed
end
def breaker(string)
begin
string.upcase!
rescue
puts "Well you messed that up, didn't you?"
return
end
string
end
Example
I have a Model user with the following method:
def number_with_hyphen
number&.insert(8, "-")
end
When I run it several times in my tests I get the following output:
users(:default).number_with_hyphen
"340909-1234"
(byebug) users(:default).number_with_hyphen
"340909--1234"
(byebug) users(:default).number_with_hyphen
"340909---1234"
(byebug) users(:default).number_with_hyphen
"340909----1234"
It changes the number ?Here are the docs https://apidock.com/ruby/v1_9_3_392/String/insert
When I restructure my method to:
def number_with_hyphen
"#{number}".insert(8, "-") if number
end
If works like expected. The output stays the same!
How would you structure the code, how would you perform the insert?
which method should I use instead. Thanks
If you're using the insert method, which in the documentation explicitly states "modifies str", then you will need to avoid doing this twice, rendering it idempotent, or use another method that doesn't mangle data.
One way is a simple regular expression to extract the components you're interested in, ignoring any dash already present:
def number_with_hyphen
if (m = number.match(/\A(\d{8})\-?(\d+)\z/))
[ m[1], m[2] ].join('-')
else
number
end
end
That ends up being really safe. If modified to accept an argument, you can test this:
number = '123456781234'
number_with_hyphen(number)
# => "12345678-1234"
number
# => "123456781234"
number_with_hyphen(number_with_hyphen(number))
# => "12345678-1234"
number_with_hyphen('1234')
# => "1234"
Calling it twice doesn't mangle anything, and any non-conforming data is sent through as-is.
Do a clone of the string:
"#{number}".clone.insert(8, '-')
In RSpec, there is matcher expect{}.to change{}.to like
expect{employee.change_name}.to change{employee.name}.to "Mike"
It is very easy to read, but is not that easy to understand how it works from language standpoint. I suppose that expect, to and change are methods, but what objects are they called at? What curly braces mean in that case?
Thank you.
change and expect are methods of self and to is a method of the result of executing change and expect. The {} expressions are blocks passed to change and expect.
The following illustrates the order of evaluation:
def self.to1(arg)
puts "to1(#{arg})"
"to1"
end
def self.to2(arg)
puts "to2(#{arg})"
"to2"
end
def self.expect
puts "expect"
yield
self
end
def self.change
puts "change"
yield
self
end
expect{puts "b1"}.to1 change{puts "b2"}.to2 "#{puts 'Mike' ; 'Mike'}"
which produces the following output:
expect
b1
change
b2
Mike
to2(Mike)
to1(to2)
=> "to1"
They are blocks in ruby.
Basically the first step towards lambda expressions, basically anonymous functions.
My goal is to replace methods in the String class with other methods that do additional work (this is for a research project). This works for many methods by writing code in the String class similar to
alias_method :center_OLD, :center
def center(args*)
r = self.send(*([:center_OLD] + args))
#do some work here
#return something
end
For some methods, I need to handle a Proc as well, which is no problem. However, for the scan method, invoking it has the side effect of setting special global variables from the regular expression match. As documented, these variables are local to the thread and the method.
Unfortunately, some Rails code makes calls to scan which makes use of the $& variable. That variable gets set inside my version of the scan method, but because it's local, it doesn't make it back to the original caller which uses the variable.
Does anyone know a way to work around this? Please let me know if the problem needs clarification.
If it helps at all, all the uses I've seen so far of the $& variable are inside a Proc passed to the scan function, so I can get the binding for that Proc. However, the user doesn't seem to be able to change $& at all, so I don't know how that will help much.
Current Code
class String
alias_method :scan_OLD, :scan
def scan(*args, &b)
begin
sargs = [:scan_OLD] + args
if b.class == Proc
r = self.send(*sargs, &b)
else
r = self.send(*sargs)
end
r
rescue => error
puts error.backtrace.join("\n")
end
end
end
Of course I'll do more things before returning r, but this even is problematic -- so for simplicity we'll stick with this. As a test case, consider:
"hello world".scan(/l./) { |x| puts x }
This works fine both with and without my version of scan. With the "vanilla" String class this produces the same thing as
"hello world".scan(/l./) { puts $&; }
Namely, it prints "ll" and "ld" and returns "hello world". With the modified string class it prints two blank lines (since $& was nil) and then returns "hello world". I'll be happy if we can get that working!
You cannot set $&, because it is derived from $~, the last MatchData.
However, $~ can be set and that actually does what you want.
The trick is to set it in the block binding.
The code is inspired by the old Ruby implementation of Pathname.
(The new code is in C and does not need to care about Ruby frame-local variables)
class String
alias_method :scan_OLD, :scan
def scan(*args, &block)
sargs = [:scan_OLD] + args
if block
self.send(*sargs) do |*bargs|
Thread.current[:string_scan_matchdata] = $~
eval("$~ = Thread.current[:string_scan_matchdata]", block.binding)
yield(*bargs)
end
else
self.send(*sargs)
end
end
end
The saving of the thread-local (well, actually fiber-local) variable seems unnecessary since it is only used to pass the value and the thread never reads any other value than the last one set. It probably is there to restore the original value (most likely nil, because the variable did not exist).
One way to avoid thread-locals at all is to create a setter of $~ as a lambda (but it does create a lambda for each call):
self.send(*sargs) do |*bargs|
eval("lambda { |m| $~ = m }", block.binding).call($~)
yield(*bargs)
end
With any of these, your example works!
I wrote simple code simulating the problem:
"hello world".scan(/l./) { |x| puts x }
"hello world".scan(/l./) { puts $&; }
class String
alias_method :origin_scan, :scan
def scan *args, &b
args.unshift :origin_scan
#mutex ||= Mutex.new
begin
self.send *args do |a|
break if !block_given?
#mutex.synchronize do
p $&
case b.arity
when 0
b.call
when 1
b.call a
end
end
end
rescue => error
p error, error.backtrace.join("\n")
end
end
end
"hello world".scan(/l./) { |x| puts x }
"hello world".scan(/l./) { puts $& }
And found the following. The change of containment of the variable $& became inside a :call function, i.e. on 3-rd step before :call $& contains a valid value, but inside the block it becomes the invalid. I guess this become due to the singularity stack and variable restoration during the change process/thread context, because, probably, :call function can't access the :scan local state.
I see two variants: the first is to avoid to use global variables in the specific function redefinitions, and second, may to dig sources of ruby more deeply.
Given any object in Ruby (on Rails), how can I write a method so that it will display that object's instance variable names and its values, like this:
#x: 1
#y: 2
#link_to_point: #<Point:0x10031b298 #y=20, #x=38>
(Update: inspect will do except for large object it is difficult to break down the variables from the 200 lines of output, like in Rails, when you request.inspect or self.inspect in the ActionView object)
I also want to be able to print <br> to the end of each instance variable's value so as to print them out nicely on a webpage.
the difficulty now seems to be that not every instance variable has an accessor, so it can't be called with obj.send(var_name)
(the var_name has the "#" removed, so "#x" becomes "x")
Update: I suppose using recursion, it can print out a more advanced version:
#<Point:0x10031b462>
#x: 1
#y: 2
#link_to_point: #<Point:0x10031b298>
#x=38
#y=20
I would probably write it like this:
class Object
def all_variables(root=true)
vars = {}
self.instance_variables.each do |var|
ivar = self.instance_variable_get(var)
vars[var] = [ivar, ivar.all_variables(false)]
end
root ? [self, vars] : vars
end
end
def string_variables(vars, lb="\n", indent="\t", current_indent="")
out = "#{vars[0].inspect}#{lb}"
current_indent += indent
out += vars[1].map do |var, ivar|
ivstr = string_variables(ivar, lb, indent, current_indent)
"#{current_indent}#{var}: #{ivstr}"
end.join
return out
end
def inspect_variables(obj, lb="\n", indent="\t", current_indent="")
string_variables(obj.all_variables, lb, indent, current_indent)
end
The Object#all_variables method produces an array containing (0) the given object and (1) a hash mapping instance variable names to arrays containing (0) the instance variable and (1) a hash mapping…. Thus, it gives you a nice recursive structure. The string_variables function prints out that hash nicely; inspect_variables is just a convenience wrapper. Thus, print inspect_variables(foo) gives you a newline-separated option, and print inspect_variables(foo, "<br />\n") gives you the version with HTML line breaks. If you want to specify the indent, you can do that too: print inspect_variables(foo, "\n", "|---") produces a (useless) faux-tree format instead of tab-based indenting.
There ought to be a sensible way to write an each_variable function to which you provide a callback (which wouldn't have to allocate the intermediate storage); I'll edit this answer to include it if I think of something. Edit 1: I thought of something.
Here's another way to write it, which I think is slightly nicer:
class Object
def each_variable(name=nil, depth=0, parent=nil, &block)
yield name, self, depth, parent
self.instance_variables.each do |var|
self.instance_variable_get(var).each_variable(var, depth+1, self, &block)
end
end
end
def inspect_variables(obj, nl="\n", indent="\t", sep=': ')
out = ''
obj.each_variable do |name, var, depth, _parent|
out += [indent*depth, name, name ? sep : '', var.inspect, nl].join
end
return out
end
The Object#each_variable method takes a number of optional arguments, which are not designed to be specified by the user; instead, they are used by the recursion to maintain state. The given block is passed (a) the name of the instance variable, or nil if the variable is the root of the recursion; (b) the variable; (c) the depth to which the recursion has descended; and (d), the parent of the current variable, or nil if said variable is the root of the recursion. The recursion is depth-first. The inspect_variables function uses this to build up a string. The obj argument is the object to iterate through; nl is the line separator; indent is the indentation to be applied at each level; and sep separates the name and the value.
Edit 2: This doesn't really add anything to the answer to your question, but: just to prove that we haven't lost anything in the reimplementation, here's a reimplementation of all_variables in terms of each_variables.
def all_variables(obj)
cur_depth = 0
root = [obj, {}]
tree = root
parents = []
prev = root
obj.each_variable do |name, var, depth, _parent|
next unless name
case depth <=> cur_depth
when -1 # We've gone back up
tree = parents.pop(cur_depth - depth)[0]
when +1 # We've gone down
parents << tree
tree = prev
else # We're at the same level
# Do nothing
end
cur_depth = depth
prev = tree[1][name] = [var, {}]
end
return root
end
I feel like it ought to be shorter, but that may not be possible; because we don't have the recursion now, we have to maintain the stack explicitly (in parents). But it is possible, so the each_variable method works just as well (and I think it's a little nicer).
I see... Antal must be giving the advanced version here...
the short version then probably is:
def p_each(obj)
obj.instance_variables.each do |v|
puts "#{v}: #{obj.instance_variable_get(v)}\n"
end
nil
end
or to return it as a string:
def sp_each(obj)
s = ""
obj.instance_variables.each do |v|
s += "#{v}: #{obj.instance_variable_get(v)}\n"
end
s
end
or shorter:
def sp_each(obj)
obj.instance_variables.map {|v| "#{v}: #{obj.instance_variable_get(v)}\n"}.join
end
This is a quick adaptation of a simple JSON emitter I wrote for another question:
class Object
def inspect!(indent=0)
return inspect if instance_variables.empty?
"#<#{self.class}:0x#{object_id.to_s(16)}\n#{' ' * indent+=1}#{
instance_variables.map {|var|
"#{var}: #{instance_variable_get(var).inspect!(indent)}"
}.join("\n#{' ' * indent}")
}\n#{' ' * indent-=1}>"
end
end
class Array
def inspect!(indent=0)
return '[]' if empty?
"[\n#{' ' * indent+=1}#{
map {|el| el.inspect!(indent) }.join(",\n#{' ' * indent}")
}\n#{' ' * indent-=1}]"
end
end
class Hash
def inspect!(indent=0)
return '{}' if empty?
"{\n#{' ' * indent+=1}#{
map {|k, v|
"#{k.inspect!(indent)} => #{v.inspect!(indent)}"
}.join(",\n#{' ' * indent}")
}\n#{' ' * indent-=1}}"
end
end
That's all the magic, really. Now we only need some simple defaults for some types where a full-on inspect doesn't really make sense (nil, false, true, numbers, etc.):
module InspectBang
def inspect!(indent=0)
inspect
end
end
[Numeric, Symbol, NilClass, TrueClass, FalseClass, String].each do |klass|
klass.send :include, InspectBang
end
Like this?
# Get the instance variables of an object
d = Date.new
d.instance_variables.each{|i| puts i + "<br />"}
Ruby Documentation on instance_variables.
The concept is commonly called "introspection", (to look into oneself).