Forum: Ruby-core Autoload treatment of absolute paths in $LOAD_PATH containing or.

Posted by David Yip (Guest)
on 2011-01-19 10:21
(Received via mailing list)
Hello all,

I've run into a behavior with autoload and $LOAD_PATH that is 
inconsistent
across Ruby versions and implementations, and would like clarification 
on what
the correct behavior should be.

Consider the two source files below:

(root)/foo.rb
-------------

    $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) + 
'/./foo')

    module Foo
      autoload :Bar, 'bar'
    end

    Foo::Bar

(root)/foo/bar.rb
-----------------

    module Foo; class Bar; end; end

An executable, expanded version of this example, along with some 
annotations, is
available at https://github.com/yipdw/autoload-testcase.

The above code will unshift a path resembling /a/./foo into $LOAD_PATH. 
This
path is absolute -- it addresses an unambiguous location in the 
filesystem --
but it is not expanded.

This example is a bit silly, but this can happen in less contrived 
situations,
such as loading libraries using

    File.join(File.dirname(__FILE__), '../a/b')

.

(I know that File.join(File.dirname(__FILE__), ...) has issues, but that 
doesn't
mean it's illegal Ruby code.)

Here are run results for the autoload-testcase example under a variety 
of Ruby
implementations and versions[*]:

    | Implementation                       | Result            |
    +--------------------------------------+-------------------+
    | Ruby 1.8.7-p330                      | resolves Foo::Bar |
    | Ruby 1.9.2-p0                        | raises NameError  |
    | Ruby 1.9.2-p136                      | raises NameError  |
    | Rubinius 1.2.0                       | resolves Foo::Bar |
    | JRuby 1.5.6, 1.8 compatibility mode  | resolves Foo::Bar |
    | JRuby 1.5.6, 1.9 compatibility mode  | resolves Foo::Bar |

A run log is available in the autoload-testcase repository.

So I guess my question can be stated as: does it make sense to permit 
absolute
paths having . and .. in $LOAD_PATH?

$LOAD_PATH can already contain relative paths; additionally, . and .. 
are
properly expanded for relative paths.  Furthermore, most shells will 
expand .
and .. in absolute paths.  Therefore, I think the answer is "yes", but I 
would
like input on this, especially as I haven't seen this issue raised 
anywhere
else.  (If it has been raised before, please let me know that, too.)

Thanks,

- David

---

[*] The exceptions thrown by Ruby 1.9.2-p0 and 1.9.2-p136 appear to be 
triggered
in part by the algorithm of rb_get_expanded_load_path(void).

In r30603 (latest revision as of this writing) the following is present 
in
rb_get_expanded_load_path at load.c:51-66:

    for (i = 0; i < RARRAY_LEN(load_path); ++i) {
  VALUE str = rb_check_string_type(RARRAY_PTR(load_path)[i]);
  if (NIL_P(str) || !rb_is_absolute_path(RSTRING_PTR(str)))
      goto relative_path_found;
    }
    return load_path;

    relative_path_found:
      ary = rb_ary_new2(RARRAY_LEN(load_path));
      for (i = 0; i < RARRAY_LEN(load_path); ++i) {
          VALUE path = rb_file_expand_path(RARRAY_PTR(load_path)[i], 
Qnil);
          rb_str_freeze(path);
          rb_ary_push(ary, path);
      }
      rb_obj_freeze(ary);
      return ary;


On non-DOSISH systems, rb_is_absolute_path expands to

    int
    rb_is_absolute_path(const char *path)
    {
      if (path[0] == '/') return 1;

      return 0;
    }

Therefore, if there are no paths present in $LOAD_PATH for which
rb_is_absolute_path returns false, paths such as /a/./b will not be 
expanded to
/a/b by rb_get_expanded_load_path.  I haven't yet studied the code long 
enough
to precisely figure out how that behavior interacts with the autoload 
mechanism
and produces the name resolution failure, but it does seem to play a 
major role.
Posted by Hedge H. (hedge_h)
on 2011-03-03 15:08
Ouch, ouch, ouch:

I was beginning to doubt my sanity until I stumbled across this post.
My Rspec (2.5.1) example was failing with

uninitialized constant B3::Bdd::Helpers (NameError)

Then, in spec_helper.rb I replaced

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

with

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

And things worked again.

Is this an acknowledged bug/issue or am I doing something illegal?
Posted by Roger Pack (Guest)
on 2011-03-10 00:32
(Received via mailing list)
> So I guess my question can be stated as: does it make sense to permit absolute
> paths having . and .. in $LOAD_PATH?

I think so. I'm thinking it's a bug, unless other disagree?
-r
Posted by James M. Lawrence (quix)
on 2011-03-10 06:04
(Received via mailing list)
On Wed, Mar 9, 2011 at 6:32 PM, Roger Pack <rogerdpack2@gmail.com> 
wrote:
> I think so. I'm thinking it's a bug, unless other disagree?

This is in the backport queue. http://redmine.ruby-lang.org/issues/4446
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.