Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updated to use latest version of ruby_parser, ruby2ruby, and sexp_processor #4

Merged
merged 1 commit into from Nov 13, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 7 additions & 4 deletions Gemfile
@@ -1,15 +1,18 @@
source "http://rubygems.org"

gem "ruby2ruby"
gem "ruby_parser"
gem 'sexp_processor', ">= 4.1.2"
gem 'ruby2ruby', ">= 2.0.1"
gem "ruby_parser", ">= 3.0.1"

# Add dependencies to develop your gem here.
# Include everything needed to run rake, tests, features, etc.
group :development do
gem "shoulda", ">= 0"
gem "rdoc", "~> 3.12"
gem "bundler", "~> 1.0.0"
gem "bundler", "~> 1.0"
gem "jeweler", "~> 1.8.3"
gem "rcov", ">= 0"
gem "rcov", :platforms => :ruby_18
gem "simplecov", :platforms => :ruby_19
gem "test-unit", :platforms => :ruby_19
gem "rake"
end
46 changes: 30 additions & 16 deletions Gemfile.lock
@@ -1,38 +1,52 @@
GEM
remote: http://rubygems.org/
specs:
activesupport (3.2.8)
i18n (~> 0.6)
multi_json (~> 1.0)
git (1.2.5)
jeweler (1.8.3)
i18n (0.6.1)
jeweler (1.8.4)
bundler (~> 1.0)
git (>= 1.2.5)
rake
rdoc
json (1.6.5)
json (1.7.5)
multi_json (1.3.6)
rake (0.9.2.2)
rcov (1.0.0)
rdoc (3.12)
json (~> 1.4)
ruby2ruby (1.3.1)
ruby_parser (~> 2.0)
sexp_processor (~> 3.0)
ruby_parser (2.3.1)
sexp_processor (~> 3.0)
sexp_processor (3.1.0)
shoulda (3.0.1)
shoulda-context (~> 1.0.0)
shoulda-matchers (~> 1.0.0)
shoulda-context (1.0.0)
shoulda-matchers (1.0.0)
ruby2ruby (2.0.1)
ruby_parser (~> 3.0.0)
sexp_processor (~> 4.0)
ruby_parser (3.0.1)
sexp_processor (~> 4.1)
sexp_processor (4.1.2)
shoulda (3.3.2)
shoulda-context (~> 1.0.1)
shoulda-matchers (~> 1.4.1)
shoulda-context (1.0.1)
shoulda-matchers (1.4.1)
activesupport (>= 3.0.0)
simplecov (0.7.1)
multi_json (~> 1.0)
simplecov-html (~> 0.7.1)
simplecov-html (0.7.1)
test-unit (2.5.2)

PLATFORMS
ruby

DEPENDENCIES
bundler (~> 1.0.0)
bundler (~> 1.0)
jeweler (~> 1.8.3)
rake
rcov
rdoc (~> 3.12)
ruby2ruby
ruby_parser
ruby2ruby (>= 2.0.1)
ruby_parser (>= 3.0.1)
sexp_processor (>= 4.1.2)
shoulda
simplecov
test-unit
20 changes: 14 additions & 6 deletions Rakefile
Expand Up @@ -46,12 +46,20 @@ Rake::TestTask.new(:test) do |test|
test.verbose = true
end

require 'rcov/rcovtask'
Rcov::RcovTask.new do |test|
test.libs << 'test'
test.pattern = 'test/**/test_*.rb'
test.verbose = true
test.rcov_opts << '--exclude "gems/*"'
if RUBY_VERSION >= "1.9"
desc "Generate coverage report for tests"
task :coverage do |cov|
ENV['COVERAGE'] = 'true'
Rake::Task[:test].execute
end
else
require 'rcov/rcovtask'
Rcov::RcovTask.new do |test|
test.libs << 'test'
test.pattern = 'test/**/test_*.rb'
test.verbose = true
test.rcov_opts << '--exclude "gems/*"'
end
end

task :default => :test
Expand Down
4 changes: 2 additions & 2 deletions lib/safemode/blankslate.rb
Expand Up @@ -3,9 +3,9 @@ class Blankslate
@@allow_instance_methods = ['class', 'inspect', 'methods', 'respond_to?', 'to_s', 'instance_variable_get']
@@allow_class_methods = ['methods', 'new', 'name', 'inspect', '<', 'ancestors', '=='] # < needed in Rails Object#subclasses_of

silently { undef_methods(*instance_methods - @@allow_instance_methods) }
silently { undef_methods(*instance_methods.map(&:to_s) - @@allow_instance_methods) }
class << self
silently { undef_methods(*instance_methods - @@allow_class_methods) }
silently { undef_methods(*instance_methods.map(&:to_s) - @@allow_class_methods) }

def method_added(name) end # ActiveSupport needs this

Expand Down
4 changes: 2 additions & 2 deletions lib/safemode/core_jails.rb
Expand Up @@ -22,7 +22,7 @@ def core_classes
end

def core_jail_methods(klass)
@@methods_whitelist[klass.name] + (@@default_methods & klass.instance_methods)
@@methods_whitelist[klass.name] + (@@default_methods & klass.instance_methods.map(&:to_s))
end
end

Expand Down Expand Up @@ -67,7 +67,7 @@ def core_jail_methods(klass)

'String' => %w(blank? capitalize capitalize! casecmp center chomp chomp!
chop chop! concat count crypt delete delete! downcase
downcase! dump each each_byte each_line empty? end_with? gsub
downcase! dump each_byte each_line empty? end_with? force_encoding gsub
gsub! hash hex include? index insert intern iseuc issjis
isutf8 kconv length ljust lstrip lstrip! match next next! oct
reverse reverse! rindex rjust rstrip rstrip! scan size slice
Expand Down
37 changes: 25 additions & 12 deletions lib/safemode/parser.rb
Expand Up @@ -36,7 +36,7 @@ def process_call(exp)
receiver = jail process_call_receiver(exp)
name = exp.shift
args = process_call_args(exp)
process_call_code(receiver, name, args)
process_call_code(receiver, name, args)
end

def process_fcall(exp)
Expand Down Expand Up @@ -79,16 +79,19 @@ def process_iasgn(exp)
:iasgn, # iasgn is sometimes allowed
# not sure about self ...
:self,
# :args is now used for block parameters
:args,
# unnecessarily advanced?
:argscat, :argspush, :splat, :block_pass,
:op_asgn1, :op_asgn2, :op_asgn_and, :op_asgn_or,
# needed for haml
:block ]

disallowed = [ # :self, # self doesn't seem to be needed for vcalls?
:const, :defn, :defs, :alias, :valias, :undef, :class, :attrset,
# see below for :const handling
:defn, :defs, :alias, :valias, :undef, :class, :attrset,
:module, :sclass, :colon2, :colon3,
:fbody, :scope, :args, :block_arg, :postexe,
:fbody, :scope, :block_arg, :postexe,
:redo, :retry, :begin, :rescue, :resbody, :ensure,
:defined, :super, :zsuper, :return,
:dmethod, :bmethod, :to_ary, :svalue, :match,
Expand All @@ -102,11 +105,18 @@ def process_iasgn(exp)
# :ifunc, :method, :last, :opt_n, :cfunc, :newline, :alloca, :memo, :cref

disallowed.each do |name|
define_method "process_#{name}" do
code = super
define_method "process_#{name}" do |arg|
code = super(arg)
raise_security_error(name, code)
end
end

# handling of Encoding constants in ruby 1.9.
# Note: ruby_parser evaluates __ENCODING__ to :const Encoding::UTF_8
def process_const(arg)
raise_security_error("constant", super(arg)) unless (RUBY_VERSION >= "1.9" and arg.sexp_type.class == Encoding)
"Encoding::#{super(arg).gsub('-', '_')}"
end

def raise_security_error(type, info)
raise Safemode::SecurityError.new(type, info)
Expand All @@ -124,14 +134,17 @@ def process_call_receiver(exp)
end

def process_call_args(exp)
args_exp = exp.shift rescue nil
if args_exp && args_exp.first == :array # FIX
args = "#{process(args_exp)[1..-2]}"
else
args = process args_exp
args = nil if args.empty?
args = []
while not exp.empty? do
args_exp = exp.shift
if args_exp && args_exp.first == :array # FIX
processed = "#{process(args_exp)[1..-2]}"
else
processed = process args_exp
end
args << processed unless (processed.nil? or processed.empty?)
end
args
args.empty? ? nil : args.join(", ")
end

def process_call_code(receiver, name, args)
Expand Down
6 changes: 3 additions & 3 deletions lib/safemode/scope.rb
Expand Up @@ -29,10 +29,10 @@ def print(*args)
def output
@_safemode_output
end

def method_missing(method, *args, &block)
if @locals.has_key?(method)
@locals[method]
@locals[method]
elsif @delegate_methods.include?(method)
@delegate.send method, *unjail_args(args), &block
else
Expand All @@ -54,5 +54,5 @@ def unjail_args(args)
arg.class.name =~ /::Jail$/ ? arg.instance_variable_get(:@source) : arg
end
end
end
end
end
19 changes: 11 additions & 8 deletions safemode.gemspec
Expand Up @@ -5,11 +5,11 @@

Gem::Specification.new do |s|
s.name = "safemode"
s.version = "1.0.1"
s.version = "1.0.2"

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Sven Fuchs", "Peter Cooper", "Matthias Viehweger", "Kingsley Hendrickse", "Ohad Levy"]
s.date = "2012-03-16"
s.date = "2012-10-24"
s.description = "A library for safe evaluation of Ruby code based on RubyParser and Ruby2Ruby. Provides Rails ActionView template handlers for ERB and Haml."
s.email = "ohadlevy@gmail.com"
s.extra_rdoc_files = [
Expand Down Expand Up @@ -56,31 +56,34 @@ Gem::Specification.new do |s|
s.specification_version = 3

if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<ruby2ruby>, [">= 0"])
s.add_runtime_dependency(%q<ruby_parser>, [">= 0"])
s.add_runtime_dependency(%q<ruby2ruby>, [">= 2.0.0.b1"])
s.add_runtime_dependency(%q<ruby_parser>, [">= 3.0.0.a9"])
s.add_development_dependency(%q<shoulda>, [">= 0"])
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
s.add_development_dependency(%q<rcov>, [">= 0"])
s.add_development_dependency(%q<simplecov>, [">= 0"])
s.add_development_dependency(%q<rake>, [">= 0"])
else
s.add_dependency(%q<ruby2ruby>, [">= 0"])
s.add_dependency(%q<ruby_parser>, [">= 0"])
s.add_dependency(%q<ruby2ruby>, [">= 2.0.0.b1"])
s.add_dependency(%q<ruby_parser>, [">= 3.0.0.a9"])
s.add_dependency(%q<shoulda>, [">= 0"])
s.add_dependency(%q<rdoc>, ["~> 3.12"])
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
s.add_dependency(%q<simplecov>, [">= 0"])
s.add_dependency(%q<rcov>, [">= 0"])
s.add_dependency(%q<rake>, [">= 0"])
end
else
s.add_dependency(%q<ruby2ruby>, [">= 0"])
s.add_dependency(%q<ruby_parser>, [">= 0"])
s.add_dependency(%q<ruby2ruby>, [">= 2.0.0.b1"])
s.add_dependency(%q<ruby_parser>, [">= 3.0.0.a9"])
s.add_dependency(%q<shoulda>, [">= 0"])
s.add_dependency(%q<rdoc>, ["~> 3.12"])
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
s.add_dependency(%q<simplecov>, [">= 0"])
s.add_dependency(%q<rcov>, [">= 0"])
s.add_dependency(%q<rake>, [">= 0"])
end
Expand Down
2 changes: 1 addition & 1 deletion test/test_erb_eval.rb
Expand Up @@ -73,4 +73,4 @@ def test_calling_#{call.gsub(/[\W]/, '_')}_should_raise_security
)
end

end
end
9 changes: 9 additions & 0 deletions test/test_helper.rb
@@ -1,3 +1,8 @@
if RUBY_VERSION >= '1.9'and ENV['COVERAGE']
require 'simplecov'
SimpleCov.start {add_filter 'test_'}
end

$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')

require 'rubygems'
Expand Down Expand Up @@ -96,6 +101,10 @@ def to_jail
def comments
[Comment.new(self), Comment.new(self)]
end

def method_missing(method, *args, &block)
super(method, *args, &block)
end
end

class Comment
Expand Down
4 changes: 2 additions & 2 deletions test/test_jail.rb
Expand Up @@ -21,7 +21,7 @@ def test_sending_to_jail_to_an_object_should_return_a_jail
def test_jail_instances_should_have_limited_methods
expected = ["class", "inspect", "method_missing", "methods", "respond_to?", "to_jail", "to_s", "instance_variable_get"]
objects.each do |object|
assert_equal expected.sort, reject_pretty_methods(object.to_jail.methods.sort)
assert_equal expected.sort, reject_pretty_methods(object.to_jail.methods.map(&:to_s).sort)
end
end

Expand All @@ -32,7 +32,7 @@ def test_jail_classes_should_have_limited_methods
"ancestors", "==" # ancestors and == needed in Rails::Generator::Spec#lookup_class
]
objects.each do |object|
assert_equal expected.sort, reject_pretty_methods(object.to_jail.class.methods.sort)
assert_equal expected.sort, reject_pretty_methods(object.to_jail.class.methods.map(&:to_s).sort)
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/test_safemode_eval.rb
Expand Up @@ -28,7 +28,7 @@ def test_should_allow_method_access_on_assigns
end

def test_should_allow_method_access_on_locals
assert_nothing_raised{ @box.eval "article.title", {}, @locals }
assert_nothing_raised{ @box.eval("article.title", {}, @locals) }
end

def test_should_not_raise_on_if_using_return_values
Expand Down