Create a gist now

Instantly share code, notes, and snippets.

@burke /ruby.diff Secret
Created Mar 27, 2017

What would you like to do?
diff --git a/file.c b/file.c
index e299244..f8819ab 100644
--- a/file.c
+++ b/file.c
@@ -5800,11 +5800,11 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level)
VALUE
rb_find_file(VALUE path)
{
- return rb_find_file_safe(path, rb_safe_level());
+ return rb_find_file_safe(path, rb_safe_level(), 0);
}
VALUE
-rb_find_file_safe(VALUE path, int safe_level)
+rb_find_file_safe(VALUE path, int safe_level, int defer_load_check)
{
VALUE tmp, load_path;
const char *f = StringValueCStr(path);
@@ -5824,7 +5824,9 @@ rb_find_file_safe(VALUE path, int safe_level)
if (safe_level >= 1 && !fpath_check(path)) {
rb_raise(rb_eSecurityError, "loading from unsafe path %s", f);
}
- if (!rb_file_load_ok(f)) return 0;
+ if (!defer_load_check && !rb_file_load_ok(f)) {
+ return 0;
+ }
if (!expanded)
path = copy_path_class(file_expand_path_1(path), path);
return path;
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index aec2d52..c7a952e 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -478,7 +478,7 @@ VALUE rb_file_s_absolute_path(int, const VALUE *);
VALUE rb_file_absolute_path(VALUE, VALUE);
VALUE rb_file_dirname(VALUE fname);
int rb_find_file_ext_safe(VALUE*, const char* const*, int);
-VALUE rb_find_file_safe(VALUE, int);
+VALUE rb_find_file_safe(VALUE, int, int);
int rb_find_file_ext(VALUE*, const char* const*);
VALUE rb_find_file(VALUE);
VALUE rb_file_directory_p(VALUE,VALUE);
diff --git a/load.c b/load.c
index 70c7345..a65446a 100644
--- a/load.c
+++ b/load.c
@@ -859,7 +859,7 @@ search_required(VALUE fname, volatile VALUE *path, int safe_level)
if (loading) *path = rb_filesystem_str_new_cstr(loading);
return 'r';
}
- if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
+ if ((tmp = rb_find_file_safe(fname, safe_level, 1)) != 0) {
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
*path = tmp;
@@ -884,7 +884,7 @@ search_required(VALUE fname, volatile VALUE *path, int safe_level)
#else
rb_str_cat2(tmp, DLEXT);
OBJ_FREEZE(tmp);
- if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) {
+ if ((tmp = rb_find_file_safe(tmp, safe_level, 0)) != 0) {
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
*path = tmp;
@@ -897,7 +897,7 @@ search_required(VALUE fname, volatile VALUE *path, int safe_level)
if (loading) *path = rb_filesystem_str_new_cstr(loading);
return 's';
}
- if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
+ if ((tmp = rb_find_file_safe(fname, safe_level, 0)) != 0) {
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
*path = tmp;
diff --git a/ruby.c b/ruby.c
index c780937..dd580bf 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1822,14 +1822,23 @@ open_load_file(VALUE fname_v, int *xflag)
rb_thread_wait_fd() release GVL. So, it's safe.
*/
rb_thread_wait_fd(fd);
+ } else if (S_ISDIR(st.st_mode)) {
+ (void)close(fd);
+ rb_load_fail(fname_v, strerror(EISDIR));
+ } else if (!S_ISREG(st.st_mode)) {
+ (void)close(fd);
+ rb_load_fail(fname_v, strerror(ENXIO));
}
}
-#endif
+#else
+ /* Note that we've replicated ruby_is_fd_loadable in S_ISFIFO without
+ * calling fstat64 twice. */
if (!ruby_is_fd_loadable(fd)) {
e = errno;
(void)close(fd);
rb_load_fail(fname_v, strerror(e));
}
+#endif
f = rb_io_fdopen(fd, mode, fname);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment