Skip to content
This repository
Browse code

formatters run better when $SAFE mode is on

Setting $SAFE=3 causes some file operations to raise a SecurityError. This patch allows you to run in SAFE mode without those SecurityErrors masking the real errors raised by the code under test and/or by RSpec matcher failures.

I extracted the SAFE setting/resetting logic into a helper method called "safely" since it's called from several places.
  • Loading branch information...
commit 576b82df34c60eb34662a96e56221e01cff35c6e 1 parent 9d8a6cc
Alex Chaffee authored April 06, 2012
4  lib/rspec/core/formatters/base_formatter.rb
@@ -117,6 +117,8 @@ def configuration
117 117
         def backtrace_line(line)
118 118
           return nil if configuration.cleaned_from_backtrace?(line)
119 119
           RSpec::Core::Metadata::relative_path(line)
  120
+        rescue SecurityError
  121
+          nil
120 122
         end
121 123
 
122 124
         def read_failed_line(exception, example)
@@ -131,6 +133,8 @@ def read_failed_line(exception, example)
131 133
           else
132 134
             "Unable to find #{file_path} to read failed line"
133 135
           end
  136
+        rescue SecurityError
  137
+          "Unable to read failed line"
134 138
         end
135 139
 
136 140
         def find_failed_line(backtrace, path)
2  lib/rspec/core/metadata.rb
@@ -31,6 +31,8 @@ def self.relative_path(line)
31 31
         line = line.sub(/\A([^:]+:\d+)$/, '\\1')
32 32
         return nil if line == '-e:1'
33 33
         line
  34
+      rescue SecurityError
  35
+        nil
34 36
       end
35 37
 
36 38
       # @private
16  spec/rspec/core/formatters/base_formatter_spec.rb
@@ -16,6 +16,12 @@
16 16
       formatter.__send__(:backtrace_line, original_line)
17 17
       original_line.should eq(File.expand_path(__FILE__))
18 18
     end
  19
+
  20
+    it "deals gracefully with a security error" do
  21
+      safely do
  22
+        formatter.__send__(:backtrace_line, __FILE__).should be_nil
  23
+      end
  24
+    end
19 25
   end
20 26
 
21 27
   describe "read_failed_line" do
@@ -32,6 +38,16 @@
32 38
       }.should_not raise_error
33 39
     end
34 40
 
  41
+    it "deals gracefully with a security error" do
  42
+      exception = mock(:Exception, :backtrace => [ "#{__FILE__}:#{__LINE__}"])
  43
+      example = mock(:Example, :file_path => __FILE__)
  44
+      safely do
  45
+        lambda {
  46
+          formatter.send(:read_failed_line, exception, example).should == "Unable to read failed line"
  47
+        }.should_not raise_error
  48
+      end
  49
+    end
  50
+
35 51
     context "when String alias to_int to_i" do
36 52
       before do
37 53
         String.class_eval do
9  spec/rspec/core/formatters/snippet_extractor_spec.rb
@@ -12,6 +12,15 @@ module Formatters
12 12
         it "falls back on a default message when it doesn't find the file" do
13 13
          RSpec::Core::Formatters::SnippetExtractor.new.lines_around("blech", 8).should eq("# Couldn't get snippet for blech")
14 14
         end
  15
+
  16
+        it "falls back on a default message when it gets a security error" do
  17
+          Thread.new {
  18
+            $SAFE = 3
  19
+            $SAFE.should == 3
  20
+            RSpec::Core::Formatters::SnippetExtractor.new.lines_around("blech", 8).should eq("# Couldn't get snippet for blech")
  21
+          }.run
  22
+          $SAFE.should == 0
  23
+        end
15 24
       end
16 25
     end
17 26
   end
20  spec/rspec/core/metadata_spec.rb
@@ -4,6 +4,26 @@ module RSpec
4 4
   module Core
5 5
     describe Metadata do
6 6
 
  7
+      describe '.relative_path' do
  8
+        let(:here) { File.expand_path(".") }
  9
+        it "transforms absolute paths to relative paths" do
  10
+          Metadata.relative_path(here).should == "."
  11
+        end
  12
+        it "transforms absolute paths to relative paths anywhere in its argument" do
  13
+          Metadata.relative_path("foo #{here} bar").should == "foo . bar"
  14
+        end
  15
+        it "returns nil if passed an unparseable file:line combo" do
  16
+          Metadata.relative_path("-e:1").should be_nil
  17
+        end
  18
+        # I have no idea what line = line.sub(/\A([^:]+:\d+)$/, '\\1') is supposed to do
  19
+        it "gracefully returns nil if run in a secure thread" do
  20
+          safely do
  21
+            Metadata.relative_path(".").should be_nil
  22
+          end
  23
+        end
  24
+
  25
+      end
  26
+
7 27
       describe "#process" do
8 28
         Metadata::RESERVED_KEYS.each do |key|
9 29
           it "prohibits :#{key} as a hash key" do
9  spec/support/helper_methods.rb
@@ -2,4 +2,13 @@ module RSpecHelpers
2 2
   def relative_path(path)
3 3
     RSpec::Core::Metadata.relative_path(path)
4 4
   end
  5
+
  6
+  def safely
  7
+    Thread.new do
  8
+      $SAFE = 3
  9
+      yield
  10
+    end.join
  11
+    $SAFE.should == 0  # just to be safe ;-)
  12
+  end
  13
+
5 14
 end

0 notes on commit 576b82d

Please sign in to comment.
Something went wrong with that request. Please try again.