Skip to content

Alias chaining does not properly restore old methods #9251

@headius

Description

@headius

In test_cgi_escape.rb there's a section that attempts to undefine the extension methods to force a test of the pure-Ruby versions. The logic looks like this:

class CGIEscapePureRubyTest < Test::Unit::TestCase
  def setup
    CGI::EscapeExt.module_eval do
      alias _escapeHTML escapeHTML
      remove_method :escapeHTML
      alias _unescapeHTML unescapeHTML
      remove_method :unescapeHTML
    end if defined?(CGI::EscapeExt) and CGI::EscapeExt.method_defined?(:escapeHTML)
  end

  def teardown
    CGI::EscapeExt.module_eval do
      alias escapeHTML _escapeHTML
      remove_method :_escapeHTML
      alias unescapeHTML _unescapeHTML
      remove_method :_unescapeHTML
    end if defined?(CGI::EscapeExt) and CGI::EscapeExt.method_defined?(:_escapeHTML)
  end

  include CGIEscapeTest::UnescapeHTMLTests
...

Unfortunately there appears to be two problems in JRuby with aliasing and re-aliasing the original method:

  • The alias should not continue to re-wrap the old alias. Instead, it should use the original alias's contents as its payload.
  • The re-aliasing of the original method does not appear to restore either the name or the class to use for super, leading to one of two errors:

Original name fails to be superable after aliasing:

CGIEscapeTest#test_cgi_escapeHTML:IBM037:
NoMethodError: super: no superclass method 'escapeHTML' for class CGI
    org/jruby/ext/cgi/escape/CGIEscape.java:402:in 'escapeHTML'
    /Users/headius/work/jruby/test/mri/cgi/test_cgi_escape.rb:208:in 'block in CGIEscapeTest'

Stack overflow due to superclass search not progressing (e.g. alias causes a lower class to be the current class, so super just keeps going back to the same class):

   org.jruby.dist/org.jruby.runtime.Helpers.invokeSuper(Helpers.java:955)
    org.jruby.dist/org.jruby.ext.cgi.escape.CGIEscape.cgiesc_unescape_html(CGIEscape.java:421)
    org.jruby.dist/org.jruby.ext.cgi.escape.CGIEscape$INVOKER$s$1$0$cgiesc_unescape_html.call(CGIEscape$INVOKER$s$1$0$cgiesc_unescape_html.gen)
    org.jruby.dist/org.jruby.internal.runtime.methods.JavaMethod$JavaMethodOneOrN.call(JavaMethod.java:966)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.internal.runtime.methods.AliasMethod.call(AliasMethod.java:131)
    org.jruby.dist/org.jruby.runtime.Helpers.invokeSuper(Helpers.java:955)
    org.jruby.dist/org.jruby.ext.cgi.escape.CGIEscape.cgiesc_unescape_html(CGIEscape.java:421)

These issues cause all of the tests to fail if the pure-Ruby tests run first due to the damage it causes to those aliased methods. I am unsure if this is a recent regression, since our older version of CGI::Escape avoided making these super calls.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions