From af24ba40344cdd83865c7c580756352be526794a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 25 Apr 2024 13:32:08 -0400 Subject: [PATCH] [PRISM] Raise LoadError when file cannot be read --- prism_compile.c | 22 +++++++++++++++++----- prism_compile.h | 2 +- ruby.c | 2 +- spec/prism.mspec | 2 -- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 26d94e979d..dd5f920fb4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -8785,7 +8785,7 @@ pm_parse_file_script_lines(const pm_scope_node_t *scope_node, const pm_parser_t * be read. */ VALUE -pm_load_file(pm_parse_result_t *result, VALUE filepath) +pm_load_file(pm_parse_result_t *result, VALUE filepath, bool load_error) { if (!pm_string_mapped_init(&result->input, RSTRING_PTR(filepath))) { #ifdef _WIN32 @@ -8794,9 +8794,21 @@ pm_load_file(pm_parse_result_t *result, VALUE filepath) int e = errno; #endif - VALUE err = rb_syserr_new(e, RSTRING_PTR(filepath)); - RB_GC_GUARD(filepath); - return err; + VALUE error; + + if (load_error) { + VALUE message = rb_str_buf_new_cstr(strerror(e)); + rb_str_cat2(message, " -- "); + rb_str_append(message, filepath); + + error = rb_exc_new3(rb_eLoadError, message); + rb_ivar_set(error, rb_intern_const("@path"), filepath); + } else { + error = rb_syserr_new(e, RSTRING_PTR(filepath)); + RB_GC_GUARD(filepath); + } + + return error; } pm_options_frozen_string_literal_init(&result->options); @@ -8843,7 +8855,7 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath) VALUE pm_load_parse_file(pm_parse_result_t *result, VALUE filepath) { - VALUE error = pm_load_file(result, filepath); + VALUE error = pm_load_file(result, filepath, false); if (NIL_P(error)) { error = pm_parse_file(result, filepath); } diff --git a/prism_compile.h b/prism_compile.h index e58bed271f..0f82782ec0 100644 --- a/prism_compile.h +++ b/prism_compile.h @@ -72,7 +72,7 @@ typedef struct { bool parsed; } pm_parse_result_t; -VALUE pm_load_file(pm_parse_result_t *result, VALUE filepath); +VALUE pm_load_file(pm_parse_result_t *result, VALUE filepath, bool load_error); VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath); VALUE pm_load_parse_file(pm_parse_result_t *result, VALUE filepath); VALUE pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath); diff --git a/ruby.c b/ruby.c index e939320f1f..d86549066d 100644 --- a/ruby.c +++ b/ruby.c @@ -2157,7 +2157,7 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result) } else { pm_options_command_line_set(options, command_line); - error = pm_load_file(result, opt->script_name); + error = pm_load_file(result, opt->script_name, true); // If reading the file did not error, at that point we load the command // line options. We do it in this order so that if the main script fails diff --git a/spec/prism.mspec b/spec/prism.mspec index 190ee6fb36..ff84fb053d 100644 --- a/spec/prism.mspec +++ b/spec/prism.mspec @@ -19,8 +19,6 @@ MSpec.register(:exclude, "Regexps with encoding modifiers preserves UTF-8 as /u MSpec.register(:exclude, "A Symbol literal raises an SyntaxError at parse time when Symbol with invalid bytes") ## Core -MSpec.register(:exclude, "IO.popen with a leading Array argument accepts a trailing Hash of Process.exec options") -MSpec.register(:exclude, "IO.popen with a leading Array argument accepts an IO mode argument following the Array") MSpec.register(:exclude, "TracePoint#inspect returns a String showing the event, method, path and line for a :return event") MSpec.register(:exclude, "TracePoint.new includes multiple events when multiple event names are passed as params") MSpec.register(:exclude, "TracePoint#path equals \"(eval at __FILE__:__LINE__)\" inside an eval for :end event")