Create a gist now

Instantly share code, notes, and snippets.

@burke /ruby.diff Secret
Last active Mar 27, 2017

What would you like to do?
diff --git a/file.c b/file.c
index e299244..0979fb9 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(), NULL);
}
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,11 @@ 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 != NULL) {
+ *defer_load_check = 1;
+ } else if (!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..ce11e66 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..1f3444d 100644
--- a/load.c
+++ b/load.c
@@ -578,7 +578,7 @@ NORETURN(static void load_failed(VALUE));
const rb_iseq_t *rb_iseq_load_iseq(VALUE fname);
static int
-rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
+rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap, int deferred_load_check)
{
int state;
volatile VALUE wrapper = th->top_wrapper;
@@ -611,6 +611,14 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
/* OK */
}
else {
+ if (deferred_load_check) {
+ const char *f = StringValueCStr(fname);
+ if (!rb_file_load_ok(f)) {
+ rb_protect((VALUE (*)(VALUE))load_failed, fname, &state);
+ goto error;
+ }
+ }
+
th->mild_compile_error++;
node = (NODE *)rb_load_file_str(fname);
iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), NULL);
@@ -618,6 +626,7 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
}
rb_iseq_eval(iseq);
}
+error:
TH_POP_TAG();
#if !defined __GNUC__
@@ -646,7 +655,7 @@ static void
rb_load_internal(VALUE fname, int wrap)
{
rb_thread_t *curr_th = GET_THREAD();
- int state = rb_load_internal0(curr_th, fname, wrap);
+ int state = rb_load_internal0(curr_th, fname, wrap, 0);
if (state) {
if (state == TAG_RAISE) rb_exc_raise(curr_th->errinfo);
JUMP_TAG(state);
@@ -678,7 +687,7 @@ rb_load_protect(VALUE fname, int wrap, int *state)
path = file_to_load(fname);
}
POP_TAG();
- if (!status) status = rb_load_internal0(GET_THREAD(), path, wrap);
+ if (!status) status = rb_load_internal0(GET_THREAD(), path, wrap, 0);
if (state)
*state = status;
}
@@ -848,7 +857,7 @@ search_required(VALUE fname, volatile VALUE *path, int safe_level)
{
VALUE tmp;
char *ext, *ftptr;
- int type, ft = 0;
+ int type, ft, defer_load_check = 0;
const char *loading;
*path = 0;
@@ -859,11 +868,14 @@ 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, &defer_load_check)) != 0) {
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
*path = tmp;
- return 'r';
+ if (defer_load_check)
+ return 'd';
+ else
+ return 'r';
}
return 0;
}
@@ -884,7 +896,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, NULL)) != 0) {
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
*path = tmp;
@@ -897,7 +909,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, NULL)) != 0) {
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
*path = tmp;
@@ -994,8 +1006,12 @@ rb_require_internal(VALUE fname, int safe)
}
else {
switch (found) {
+ case 'd':
+ state = rb_load_internal0(th, path, 0, 1);
+ break;
+
case 'r':
- state = rb_load_internal0(th, path, 0);
+ state = rb_load_internal0(th, path, 0, 0);
break;
case 's':
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment