Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 214dea5ba2f6
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e5e519837958
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Apr 21, 2015

  1. Re-fix searching of prepended modules-in-a-module. Fixes #2864.

    The original problem was that we only searched the target module's
    method table, which is empty in the presence of prepends. The new
    issue was that my depth-limiting fix to IncludedModuleWrapper's
    searchMethodCommon did not start from the right place (`this`
    instead of `origin`) and the condition was not right.
    headius committed Apr 21, 2015
    Copy the full SHA
    b9473af View commit details
  2. Copy the full SHA
    e5e5198 View commit details
Showing with 58 additions and 21 deletions.
  1. +6 −4 core/src/main/java/org/jruby/IncludedModuleWrapper.java
  2. +21 −0 spec/regression/GH-2864_search_prepends_in_modules_spec.rb
  3. +31 −17 test/mri/ruby/test_m17n_comb.rb
10 changes: 6 additions & 4 deletions core/src/main/java/org/jruby/IncludedModuleWrapper.java
Original file line number Diff line number Diff line change
@@ -208,14 +208,16 @@ public IRubyObject getAutoloadConstant(String name) {

@Override
protected DynamicMethod searchMethodCommon(String name) {
// IncludedModuleWrapper needs to search prepended modules too, but not included ones.
RubyModule module = this;
for (; module.isPrepended(); module = module.getSuperClass()) {
// IncludedModuleWrapper needs to search prepended modules too, so search until we find methodLocation
RubyModule module = origin;
RubyModule methodLoc = origin.getMethodLocation();

for (; module != methodLoc; module = module.getSuperClass()) {
DynamicMethod method = module.getMethods().get(name);
if (method != null) return method.isNull() ? null : method;
}

// Last non-prepended module should be our regular module, do one last search.
// one last search for method location
DynamicMethod method = module.getMethods().get(name);
if (method != null) return method.isNull() ? null : method;

21 changes: 21 additions & 0 deletions spec/regression/GH-2864_search_prepends_in_modules_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# The issue here stemmed from modules with prepends not being searched like classes with prepends. Instead of searching
# up the prepend hierarchy, we only ever checked the target module's method table. When a prepend was active, this
# table is empty. The modified logic now searches all modules in hierarchy below and including the original, allowing
# it to search prepended modules-in-a-module correctly. #2864
describe "A module with prepends" do
it "is searched as a hierarchy" do
a = Module.new do
def foo; 1; end
end
b = Module.new
a.prepend(b)
x = Class.new do
include a
end
y = Class.new(x) do
prepend b
end

expect(y.new.foo).to eq(1)
end
end
48 changes: 31 additions & 17 deletions test/mri/ruby/test_m17n_comb.rb
Original file line number Diff line number Diff line change
@@ -730,27 +730,41 @@ def test_str_count
}
end

# glibc 2.16 or later denies salt contained other than [0-9A-Za-z./] #7312
# we use this check to test strict and non-strict behavior separately #11045
strict_crypt = if defined? Etc::CS_GNU_LIBC_VERSION
glibcver = Etc.confstr(Etc::CS_GNU_LIBC_VERSION).scan(/\d+/).map(&:to_i)
(glibcver <=> [2, 16]) >= 0
end

def test_str_crypt
strict_crypt = true # default to skipping non-alphanum salt
combination(STRINGS, STRINGS) {|str, salt|
# skip input other than [0-9A-Za-z./] to confirm strict behavior
next unless salt.ascii_only? && /\A[0-9a-zA-Z.\/]+\z/ =~ salt

# glibc 2.16 or later denies salt contained other than [0-9A-Za-z./] #7312
if defined? Etc::CS_GNU_LIBC_VERSION
glibcver = Etc.confstr(Etc::CS_GNU_LIBC_VERSION).scan(/\d+/).map(&:to_i)
strict_crypt = (glibcver <=> [2, 16]) >= 0
confirm_crypt_result(str, salt)
}
end

if !strict_crypt
def test_str_crypt_nonstrict
combination(STRINGS, STRINGS) {|str, salt|
# only test input other than [0-9A-Za-z./] to confirm non-strict behavior
next if salt.ascii_only? && /\A[0-9a-zA-Z.\/]+\z/ =~ salt

confirm_crypt_result(str, salt)
}
end
end

combination(STRINGS, STRINGS) {|str, salt|
if strict_crypt
next unless salt.ascii_only? && /\A[0-9a-zA-Z.\/]+\z/ =~ salt
end
if b(salt).length < 2
assert_raise(ArgumentError) { str.crypt(salt) }
next
end
t = str.crypt(salt)
assert_equal(b(str).crypt(b(salt)), t, "#{encdump(str)}.crypt(#{encdump(salt)})")
assert_encoding('ASCII-8BIT', t.encoding)
}
private def confirm_crypt_result(str, salt)
if b(salt).length < 2
assert_raise(ArgumentError) { str.crypt(salt) }
return
end
t = str.crypt(salt)
assert_equal(b(str).crypt(b(salt)), t, "#{encdump(str)}.crypt(#{encdump(salt)})")
assert_encoding('ASCII-8BIT', t.encoding)
end

def test_str_delete