Project

General

Profile

Backport #8070 ยป backport-8034-ruby_1_9_3.diff

luislavena (Luis Lavena), 03/14/2013 02:03 PM

View differences:

ChangeLog
Thu Mar 14 12:53:15 2013 Luis Lavena <luislavena@gmail.com>
* win32/file.c (get_user_from_path): add internal function that retrieves
username from supplied path (refactored).
* win32/file.c (rb_file_expand_path_internal): refactor expansion of user
home to use get_user_from_path and cover dir_string corner cases.
[ruby-core:53168] [Bug #8034]
Sun Mar 10 23:38:15 2013 Luis Lavena <luislavena@gmail.com>
* win32/file.c (rb_file_expand_path_internal): Expand home directory when
used as second parameter (dir_string). [ruby-core:53168] [Bug #8034]
* test/ruby/test_file_exhaustive.rb: add test to verify.
Tue Feb 26 09:53:59 2013 NARUSE, Yui <naruse@ruby-lang.org>
* st.c (st_add_direct): int is not always same with st_index_t. some
test/ruby/test_file_exhaustive.rb
end
end
UnknownUserHome = "~foo_bar_baz_unknown_user_wahaha".freeze
def test_expand_path_home
assert_kind_of(String, File.expand_path("~")) if ENV["HOME"]
assert_raise(ArgumentError) { File.expand_path("~foo_bar_baz_unknown_user_wahaha") }
assert_raise(ArgumentError) { File.expand_path("~foo_bar_baz_unknown_user_wahaha", "/") }
assert_raise(ArgumentError) { File.expand_path(UnknownUserHome) }
assert_raise(ArgumentError) { File.expand_path(UnknownUserHome, "/") }
begin
bug3630 = '[ruby-core:31537]'
home = ENV["HOME"]
......
end
end
def test_expand_path_home_dir_string
home = ENV["HOME"]
new_home = "#{DRIVE}/UserHome"
ENV["HOME"] = new_home
bug8034 = "[ruby-core:53168]"
assert_equal File.join(new_home, "foo"), File.expand_path("foo", "~"), bug8034
assert_equal File.join(new_home, "bar", "foo"), File.expand_path("foo", "~/bar"), bug8034
assert_raise(ArgumentError) { File.expand_path(".", UnknownUserHome) }
assert_nothing_raised(ArgumentError) { File.expand_path("#{DRIVE}/", UnknownUserHome) }
ensure
ENV["HOME"] = home
end
def test_expand_path_remove_trailing_alternative_data
assert_equal File.join(@rootdir, "aaa"), File.expand_path("#{@rootdir}/aaa::$DATA")
assert_equal File.join(@rootdir, "aa:a"), File.expand_path("#{@rootdir}/aa:a:$DATA")
win32/file.c
return size;
}
static inline VALUE
get_user_from_path(wchar_t **wpath, int offset, UINT cp, UINT path_cp, rb_encoding *path_encoding)
{
VALUE result, tmp;
wchar_t *wuser = *wpath + offset;
wchar_t *pos = wuser;
char *user;
size_t size;
while (!IS_DIR_SEPARATOR_P(*pos) && *pos != '\0')
pos++;
*pos = '\0';
convert_wchar_to_mb(wuser, &user, &size, cp);
/* convert to VALUE and set the path encoding */
if (path_cp == INVALID_CODE_PAGE) {
tmp = rb_enc_str_new(user, size, rb_utf8_encoding());
result = rb_str_encode(tmp, rb_enc_from_encoding(path_encoding), 0, Qnil);
rb_str_resize(tmp, 0);
}
else {
result = rb_enc_str_new(user, size, path_encoding);
}
if (user)
xfree(user);
return result;
}
VALUE
rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)
{
size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0;
size_t buffer_len = 0;
char *fullpath = NULL;
wchar_t *wfullpath = NULL, *wpath = NULL, *wpath_pos = NULL, *wdir = NULL;
wchar_t *wfullpath = NULL, *wpath = NULL, *wpath_pos = NULL;
wchar_t *wdir = NULL, *wdir_pos = NULL;
wchar_t *whome = NULL, *buffer = NULL, *buffer_pos = NULL;
UINT path_cp, cp;
VALUE path = fname, dir = dname;
......
}
}
else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L'~') {
wchar_t *wuser = wpath_pos + 1;
wchar_t *pos = wuser;
char *user;
/* tainted if expanding '~' */
tainted = 1;
while (!IS_DIR_SEPARATOR_P(*pos) && *pos != '\0')
pos++;
result = get_user_from_path(&wpath_pos, 1, cp, path_cp, path_encoding);
*pos = '\0';
convert_wchar_to_mb(wuser, &user, &size, cp);
/* convert to VALUE and set the path encoding */
if (path_cp == INVALID_CODE_PAGE) {
VALUE tmp = rb_enc_str_new(user, size, rb_utf8_encoding());
result = rb_str_encode(tmp, rb_enc_from_encoding(path_encoding), 0, Qnil);
rb_str_resize(tmp, 0);
}
else {
result = rb_enc_str_new(user, size, path_encoding);
}
xfree(wpath);
if (user)
xfree(user);
if (wpath)
xfree(wpath);
rb_raise(rb_eArgError, "can't find user %s", StringValuePtr(result));
}
......
}
/* convert char * to wchar_t */
convert_mb_to_wchar(dir, &wdir, NULL, &wdir_len, cp);
convert_mb_to_wchar(dir, &wdir, &wdir_pos, &wdir_len, cp);
if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L'~' &&
(wdir_len == 1 || IS_DIR_SEPARATOR_P(wdir_pos[1]))) {
/* tainted if expanding '~' */
tainted = 1;
if (wdir_len >= 2 && wdir[1] == L':') {
whome = home_dir();
if (whome == NULL) {
xfree(wpath);
xfree(wdir);
rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
}
whome_len = wcslen(whome);
if (PathIsRelativeW(whome) && !(whome_len >= 2 && IS_DIR_UNC_P(whome))) {
xfree(wpath);
xfree(wdir);
rb_raise(rb_eArgError, "non-absolute home");
}
/* exclude ~ from the result */
wdir_pos++;
wdir_len--;
/* exclude separator if present */
if (wdir_len && IS_DIR_SEPARATOR_P(wdir_pos[0])) {
wdir_pos++;
wdir_len--;
}
}
else if (wdir_len >= 2 && wdir[1] == L':') {
dir_drive = wdir[0];
if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) {
wdir_len = 2;
......
wdir_len = pos - 1;
}
}
else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] == L'~') {
result = get_user_from_path(&wdir_pos, 1, cp, path_cp, path_encoding);
if (wpath)
xfree(wpath);
if (wdir)
xfree(wdir);
rb_raise(rb_eArgError, "can't find user %s", StringValuePtr(result));
}
}
/* determine if we ignore dir or not */
......
if (!tainted && OBJ_TAINTED(dir))
tainted = 1;
wcsncpy(buffer_pos, wdir, wdir_len);
wcsncpy(buffer_pos, wdir_pos, wdir_len);
buffer_pos += wdir_len;
}
    (1-1/1)