зеркало из https://github.com/github/ruby.git
Fixed stack overflow [Bug #16382]
Get rid of infinite recursion in expanding a load path to the real path while loading a transcoder.
This commit is contained in:
Родитель
8bddf1bc9b
Коммит
14a17063a1
33
file.c
33
file.c
|
@ -242,7 +242,7 @@ rb_str_encode_ospath(VALUE path)
|
|||
encidx = rb_filesystem_encindex();
|
||||
}
|
||||
#endif
|
||||
if (encidx != ENCINDEX_UTF_8) {
|
||||
if (encidx != ENCINDEX_ASCII && encidx != ENCINDEX_UTF_8) {
|
||||
rb_encoding *enc = rb_enc_from_index(encidx);
|
||||
rb_encoding *utf8 = rb_utf8_encoding();
|
||||
path = rb_str_conv_enc(path, enc, utf8);
|
||||
|
@ -4243,7 +4243,7 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE f
|
|||
}
|
||||
|
||||
static VALUE
|
||||
rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode)
|
||||
rb_check_realpath_emulate(VALUE basedir, VALUE path, rb_encoding *origenc, enum rb_realpath_mode mode)
|
||||
{
|
||||
long prefixlen;
|
||||
VALUE resolved;
|
||||
|
@ -4251,7 +4251,7 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode)
|
|||
VALUE loopcheck;
|
||||
VALUE curdir = Qnil;
|
||||
|
||||
rb_encoding *enc, *origenc;
|
||||
rb_encoding *enc;
|
||||
char *path_names = NULL, *basedir_names = NULL, *curdir_names = NULL;
|
||||
char *ptr, *prefixptr = NULL, *pend;
|
||||
long len;
|
||||
|
@ -4264,7 +4264,6 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode)
|
|||
}
|
||||
|
||||
enc = rb_enc_get(unresolved_path);
|
||||
origenc = enc;
|
||||
unresolved_path = TO_OSPATH(unresolved_path);
|
||||
RSTRING_GETMEM(unresolved_path, ptr, len);
|
||||
path_names = skipprefixroot(ptr, ptr + len, rb_enc_get(unresolved_path));
|
||||
|
@ -4322,7 +4321,7 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode)
|
|||
if (realpath_rec(&prefixlen, &resolved, path_names, Qnil, loopcheck, mode, 1))
|
||||
return Qnil;
|
||||
|
||||
if (origenc != rb_enc_get(resolved)) {
|
||||
if (origenc && origenc != rb_enc_get(resolved)) {
|
||||
if (rb_enc_str_asciionly_p(resolved)) {
|
||||
rb_enc_associate(resolved, origenc);
|
||||
}
|
||||
|
@ -4339,25 +4338,23 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, enum rb_realpath_mode mode)
|
|||
static VALUE rb_file_join(VALUE ary);
|
||||
|
||||
static VALUE
|
||||
rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode)
|
||||
rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum rb_realpath_mode mode)
|
||||
{
|
||||
#ifdef HAVE_REALPATH
|
||||
VALUE unresolved_path;
|
||||
rb_encoding *origenc;
|
||||
char *resolved_ptr = NULL;
|
||||
VALUE resolved;
|
||||
struct stat st;
|
||||
|
||||
if (mode == RB_REALPATH_DIR) {
|
||||
return rb_check_realpath_emulate(basedir, path, mode);
|
||||
return rb_check_realpath_emulate(basedir, path, origenc, mode);
|
||||
}
|
||||
|
||||
unresolved_path = rb_str_dup_frozen(path);
|
||||
origenc = rb_enc_get(unresolved_path);
|
||||
if (*RSTRING_PTR(unresolved_path) != '/' && !NIL_P(basedir)) {
|
||||
unresolved_path = rb_file_join(rb_assoc_new(basedir, unresolved_path));
|
||||
}
|
||||
unresolved_path = TO_OSPATH(unresolved_path);
|
||||
if (origenc) unresolved_path = TO_OSPATH(unresolved_path);
|
||||
|
||||
if ((resolved_ptr = realpath(RSTRING_PTR(unresolved_path), NULL)) == NULL) {
|
||||
/* glibc realpath(3) does not allow /path/to/file.rb/../other_file.rb,
|
||||
|
@ -4367,7 +4364,7 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode
|
|||
Fallback to the emulated approach in either of those cases. */
|
||||
if (errno == ENOTDIR ||
|
||||
(errno == ENOENT && rb_file_exist_p(0, unresolved_path))) {
|
||||
return rb_check_realpath_emulate(basedir, path, mode);
|
||||
return rb_check_realpath_emulate(basedir, path, origenc, mode);
|
||||
|
||||
}
|
||||
if (mode == RB_REALPATH_CHECK) {
|
||||
|
@ -4378,14 +4375,16 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode
|
|||
resolved = ospath_new(resolved_ptr, strlen(resolved_ptr), rb_filesystem_encoding());
|
||||
free(resolved_ptr);
|
||||
|
||||
if (rb_stat(resolved, &st) < 0) {
|
||||
/* As `resolved` is a String in the filesystem encoding, no
|
||||
* conversion is needed */
|
||||
if (stat_without_gvl(RSTRING_PTR(resolved), &st) < 0) {
|
||||
if (mode == RB_REALPATH_CHECK) {
|
||||
return Qnil;
|
||||
}
|
||||
rb_sys_fail_path(unresolved_path);
|
||||
}
|
||||
|
||||
if (origenc != rb_enc_get(resolved)) {
|
||||
if (origenc && origenc != rb_enc_get(resolved)) {
|
||||
if (!rb_enc_str_asciionly_p(resolved)) {
|
||||
resolved = rb_str_conv_enc(resolved, NULL, origenc);
|
||||
}
|
||||
|
@ -4402,7 +4401,7 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode
|
|||
RB_GC_GUARD(unresolved_path);
|
||||
return resolved;
|
||||
#else
|
||||
return rb_check_realpath_emulate(basedir, path, mode);
|
||||
return rb_check_realpath_emulate(basedir, path, origenc, mode);
|
||||
#endif /* HAVE_REALPATH */
|
||||
}
|
||||
|
||||
|
@ -4411,13 +4410,13 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict)
|
|||
{
|
||||
const enum rb_realpath_mode mode =
|
||||
strict ? RB_REALPATH_STRICT : RB_REALPATH_DIR;
|
||||
return rb_check_realpath_internal(basedir, path, mode);
|
||||
return rb_check_realpath_internal(basedir, path, rb_enc_get(path), mode);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_check_realpath(VALUE basedir, VALUE path)
|
||||
rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *enc)
|
||||
{
|
||||
return rb_check_realpath_internal(basedir, path, RB_REALPATH_CHECK);
|
||||
return rb_check_realpath_internal(basedir, path, enc, RB_REALPATH_CHECK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1583,7 +1583,9 @@ extern const char ruby_null_device[];
|
|||
VALUE rb_home_dir_of(VALUE user, VALUE result);
|
||||
VALUE rb_default_home_dir(VALUE result);
|
||||
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict);
|
||||
VALUE rb_check_realpath(VALUE basedir, VALUE path);
|
||||
#ifdef RUBY_ENCODING_H
|
||||
VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *origenc);
|
||||
#endif
|
||||
void rb_file_const(const char*, VALUE);
|
||||
int rb_file_load_ok(const char *);
|
||||
VALUE rb_file_expand_path_fast(VALUE, VALUE);
|
||||
|
|
2
load.c
2
load.c
|
@ -79,7 +79,7 @@ rb_construct_expanded_load_path(enum expand_type type, int *has_relative, int *h
|
|||
if (is_string)
|
||||
rb_str_freeze(path);
|
||||
as_str = rb_get_path_check_convert(as_str);
|
||||
expanded_path = rb_check_realpath(Qnil, as_str);
|
||||
expanded_path = rb_check_realpath(Qnil, as_str, NULL);
|
||||
if (NIL_P(expanded_path)) expanded_path = as_str;
|
||||
rb_ary_push(ary, rb_fstring(expanded_path));
|
||||
}
|
||||
|
|
|
@ -123,4 +123,15 @@ class TestEncoding < Test::Unit::TestCase
|
|||
assert_include(e.message, "/regexp/sQ\n")
|
||||
end;
|
||||
end
|
||||
|
||||
def test_nonascii_library_path
|
||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}".force_encoding("US-ASCII"))
|
||||
begin;
|
||||
assert_equal(Encoding::US_ASCII, __ENCODING__)
|
||||
$:.unshift("/\x80")
|
||||
assert_raise_with_message(LoadError, /\[Bug #16382\]/) do
|
||||
$:.resolve_feature_path "[Bug #16382]"
|
||||
end
|
||||
end;
|
||||
end
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче