Skip to content

Commit

Permalink
Use realpaths in Cache @path_obj
Browse files Browse the repository at this point in the history
If file is required from symlinked directory, $LOAD_PATH can have symlinked
path, while subsequent `require`s are resolved to the real path, so we can
end up in situation when we rerequire the same file with different path,
`require` loads the file again and things go BOOM.
```
From: /…/src/bootsnap/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb @ line 18 Kernel#require:

    15: def require(path)
    16:   if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
    17:     binding.pry if path == 'set'
 => 18:     require_without_cache(resolved)
    19:   else
    20:     raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
    21:   end
    22: rescue Bootsnap::LoadPathCache::ReturnFalse
    23:   return false
    24: rescue Bootsnap::LoadPathCache::FallbackScan
    25:   require_without_cache(path)
    26: end

[1] pry(main)> path
=> "set"
[2] pry(main)> Set.new.method(:to_s).source_location
=> ["/real_path/.rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/set.rb", 629]
[3] pry(main)> resolved
=> "/symlinked_path/.rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/set.rb"
[4] pry(main)> require_without_cache(resolved)
/symlinked_path/.rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/set.rb:625: warning: already initialized constant Set::InspectKey
/real_path/.rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/set.rb:625: warning: previous definition of InspectKey was here
=> true
[5] pry(main)> Set.new.method(:to_s).source_location
=> ["/symlinked_path/.rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/set.rb", 629]
[6] pry(main)>
```
  • Loading branch information
ojab committed Mar 29, 2018
1 parent 7a85e73 commit 1cd87f3
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion lib/bootsnap/load_path_cache/cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def initialize(store, path_obj, development_mode: false)
@development_mode = development_mode
@store = store
@mutex = defined?(::Mutex) ? ::Mutex.new : ::Thread::Mutex.new # TODO: Remove once Ruby 2.2 support is dropped.
@path_obj = path_obj
@path_obj = path_obj.map { |f| File.exist?(f) ? File.realpath(f) : f }
@has_relative_paths = nil
reinitialize
end
Expand Down

0 comments on commit 1cd87f3

Please sign in to comment.