class SafeRuby

Constants

DEFAULTS
MAJOR_VERSION
MINOR_VERSION
RELEASE_VERSION
VERSION

Public Class Methods

check(code, expected) click to toggle source
# File lib/safe_ruby/runner.rb, line 52
def self.check(code, expected)
  eval(code) == eval(expected)
end
eval(code, options={}) click to toggle source
# File lib/safe_ruby/runner.rb, line 19
def self.eval(code, options={})
  new(code, options).eval
end
new(code, options={}) click to toggle source
# File lib/safe_ruby/runner.rb, line 11
def initialize(code, options={})
  options = DEFAULTS.merge(options)

  @code         = code
  @raise_errors = options[:raise_errors]
  @timeout      = options[:timeout]
end

Public Instance Methods

eval() click to toggle source
# File lib/safe_ruby/runner.rb, line 23
def eval
  temp = build_tempfile
  read, write = IO.pipe
  ChildProcess.build("ruby", temp.path).tap do |process|
    process.io.stdout = write
    process.io.stderr = write
    process.start
    begin
      process.poll_for_exit(@timeout)
    rescue ChildProcess::TimeoutError => e
      process.stop # tries increasingly harsher methods to kill the process.
      return e.message
    end
    write.close
    temp.unlink
  end

  data = read.read
  begin
    Marshal.load(data)
  rescue => e
    if @raise_errors
      raise data
    else
      return data
    end
  end
end

Private Instance Methods

build_tempfile() click to toggle source
# File lib/safe_ruby/runner.rb, line 59
  def build_tempfile
    file = Tempfile.new('saferuby')
    file.write(MAKE_SAFE_CODE)
    file.write <<-STRING
      result = eval(%q(#{@code}))
      print Marshal.dump(result)
    STRING
    file.rewind
    file
  end