bootsnap 1.21.0 → 1.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adb5e1d46d7560b403e6ef7051f9ad2ef21feca194c41f0af77f2e73d6e06508
4
- data.tar.gz: cebcb8c52f1da65f13c531d05f5150fbe2b54d3fa51e0122b2cf4f2998cb63b9
3
+ metadata.gz: 4ca69038da7071534a7279f36d694ec5bcf5687272d091b314372b1f3195831b
4
+ data.tar.gz: c5dc747c2c66a71881d99af980085c06bfc378134d25712c51221b7fb6a6c03a
5
5
  SHA512:
6
- metadata.gz: 6ff78c410b363a8e2fbc9e370b684865a3aaa45e6de961d9d8dd6b1207fa2002a4d0115751ad5b259e21d69d215a4859587da79386e3b6d0cdde7e54205620d2
7
- data.tar.gz: bac1b52dfad5b0e0e1e03e6feeeb2c9d3555608410b7a73fc005e044bf31641aa8bdd72bf4f595eee69b7c58e4701579c5e6961a4937246567ef097bb9956aaf
6
+ metadata.gz: 9da2aa5050b26d377f46d1de5e8424168e0a60b00160d43ebdaf9f93c4a9006931bf6463a24afa6dd76559ccedc4ce3798d48733d5000a7a5eac08d7c7a03510
7
+ data.tar.gz: 17a8da7a372189c22f400f5c059947f98c6aa7836390965c92e6e173970a61e2e6aa57d77d3dd11a9ecea0afd729512a115fd38a21c7a30850d1e9bd662b7d26
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Unreleased
2
2
 
3
+ # 1.21.1
4
+
5
+ * Prevent a Ruby crash while scanning load path if `opendir` fails without setting `errno`.
6
+ According to the C spec this should not happen, but according to user reports, it did.
7
+
3
8
  # 1.21.0
4
9
 
5
10
  * Fix the `require` decorator to handle `Bootsnap.unload_cache!` being called.
@@ -21,6 +21,10 @@
21
21
  #include <sys/stat.h>
22
22
  #include <dirent.h>
23
23
 
24
+ #ifndef RBIMPL_ATTR_NORETURN
25
+ #define RBIMPL_ATTR_NORETURN()
26
+ #endif
27
+
24
28
  #ifdef __APPLE__
25
29
  // The symbol is present, however not in the headers
26
30
  // See: https://github.com/rails/bootsnap/issues/470
@@ -152,6 +156,21 @@ bs_rb_get_path(VALUE self, VALUE fname)
152
156
  }
153
157
 
154
158
  #ifdef HAVE_FSTATAT
159
+
160
+ RBIMPL_ATTR_NORETURN()
161
+ static void
162
+ bs_syserr_fail_path(const char *func_name, int n, VALUE path)
163
+ {
164
+ rb_syserr_fail_str(n, rb_sprintf("%s @ %s", func_name, RSTRING_PTR(path)));
165
+ }
166
+
167
+ RBIMPL_ATTR_NORETURN()
168
+ static void
169
+ bs_syserr_fail_dir_entry(const char *func_name, int n, VALUE dir, const char *d_name)
170
+ {
171
+ rb_syserr_fail_str(n, rb_sprintf("%s @ %s/%s", func_name, RSTRING_PTR(dir), d_name));
172
+ }
173
+
155
174
  static VALUE
156
175
  bs_rb_scan_dir(VALUE self, VALUE abspath)
157
176
  {
@@ -167,7 +186,17 @@ bs_rb_scan_dir(VALUE self, VALUE abspath)
167
186
  if (errno == ENOTDIR || errno == ENOENT) {
168
187
  return result;
169
188
  }
170
- rb_sys_fail("opendir");
189
+
190
+ // BUG: Some users reported a crash here because Ruby's syserr trigger
191
+ // a crash if called with `errno == 0`.
192
+ // The opendir spec is quite clear that if it returns NULL, then `errno` must
193
+ // be set, and yet here we are.
194
+ // So turning no errno into EINVAL, and from there I hope to get to the bottom of things.
195
+ if (errno == 0) {
196
+ errno = EINVAL;
197
+ }
198
+
199
+ bs_syserr_fail_path("opendir", errno, abspath);
171
200
  return Qundef;
172
201
  }
173
202
 
@@ -185,7 +214,9 @@ bs_rb_scan_dir(VALUE self, VALUE abspath)
185
214
  if (dfd < 0) {
186
215
  dfd = dirfd(dirp);
187
216
  if (dfd < 0) {
188
- rb_sys_fail("dirfd");
217
+ int err = errno;
218
+ closedir(dirp);
219
+ bs_syserr_fail_path("dirfd", err, abspath);
189
220
  return Qundef;
190
221
  }
191
222
  }
@@ -193,9 +224,12 @@ bs_rb_scan_dir(VALUE self, VALUE abspath)
193
224
  if (fstatat(dfd, entry->d_name, &st, 0)) {
194
225
  if (errno == ENOENT) {
195
226
  // Broken symlinK
227
+ errno = 0;
196
228
  continue;
197
229
  }
198
- rb_sys_fail("fstatat");
230
+ int err = errno;
231
+ closedir(dirp);
232
+ bs_syserr_fail_dir_entry("fstatat", err, abspath, entry->d_name);
199
233
  return Qundef;
200
234
  }
201
235
 
@@ -226,7 +260,7 @@ bs_rb_scan_dir(VALUE self, VALUE abspath)
226
260
  }
227
261
 
228
262
  if (closedir(dirp)) {
229
- rb_sys_fail("closedir");
263
+ bs_syserr_fail_path("closedir", errno, abspath);
230
264
  return Qundef;
231
265
  }
232
266
  return result;
@@ -102,6 +102,13 @@ module Bootsnap
102
102
  end
103
103
 
104
104
  all_requirables
105
+ rescue SystemCallError => error
106
+ if ENV["BOOTSNAP_DEBUG"]
107
+ raise
108
+ else
109
+ Bootsnap.logger&.call("Unexpected error: #{error.class}: #{error.message}")
110
+ ruby_call(root_path)
111
+ end
105
112
  end
106
113
  alias_method :call, :native_call
107
114
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bootsnap
4
- VERSION = "1.21.0"
4
+ VERSION = "1.21.1"
5
5
  end
data/lib/bootsnap.rb CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  require_relative "bootsnap/version"
4
4
  require_relative "bootsnap/bundler"
5
- require_relative "bootsnap/compile_cache"
6
- require_relative "bootsnap/load_path_cache"
7
5
 
8
6
  module Bootsnap
9
7
  InvalidConfiguration = Class.new(StandardError)
@@ -164,3 +162,6 @@ module Bootsnap
164
162
  end
165
163
  end
166
164
  end
165
+
166
+ require_relative "bootsnap/compile_cache"
167
+ require_relative "bootsnap/load_path_cache"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsnap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.0
4
+ version: 1.21.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey