summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/check_branch.yml2
-rw-r--r--.github/workflows/macos.yml16
-rw-r--r--.github/workflows/mjit.yml18
-rw-r--r--.github/workflows/ubuntu.yml18
-rw-r--r--.github/workflows/windows.yml15
-rw-r--r--appveyor.yml2
-rw-r--r--configure.ac31
-rw-r--r--cont.c3
-rw-r--r--enc/Makefile.in2
-rwxr-xr-xext/extmk.rb5
-rw-r--r--ext/openssl/History.md10
-rw-r--r--ext/openssl/extconf.rb4
-rw-r--r--ext/openssl/openssl.gemspec4
-rw-r--r--ext/openssl/ossl_version.h2
-rw-r--r--ext/zlib/zlib.c118
-rw-r--r--file.c44
-rw-r--r--io.c7
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb4
-rw-r--r--lib/bundler/vendor/uri/lib/uri/version.rb2
-rw-r--r--lib/cgi/cookie.rb44
-rw-r--r--lib/cgi/core.rb45
-rw-r--r--lib/cgi/version.rb2
-rw-r--r--lib/mkmf.rb6
-rw-r--r--lib/net/http/header.rb8
-rw-r--r--lib/time.rb4
-rw-r--r--lib/uri/rfc3986_parser.rb4
-rw-r--r--lib/uri/version.rb2
-rw-r--r--load.c2
-rw-r--r--method.h1
-rw-r--r--missing/dtoa.c3
-rw-r--r--mjit_worker.c11
-rw-r--r--numeric.c2
-rw-r--r--parse.y74
-rw-r--r--ruby.c18
-rw-r--r--spec/bundler/cache/git_spec.rb3
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb6
-rw-r--r--spec/bundler/update/git_spec.rb3
-rw-r--r--spec/ruby/core/time/shared/local.rb2
-rw-r--r--spec/ruby/library/cgi/cookie/name_spec.rb12
-rw-r--r--spec/ruby/library/cgi/cookie/parse_spec.rb10
-rw-r--r--st.c1
-rw-r--r--test/cgi/test_cgi_cookie.rb82
-rw-r--r--test/cgi/test_cgi_header.rb8
-rw-r--r--test/ripper/test_parser_events.rb13
-rw-r--r--test/ruby/test_alias.rb29
-rw-r--r--test/ruby/test_enum.rb11
-rw-r--r--test/ruby/test_exception.rb21
-rw-r--r--test/ruby/test_fiber.rb6
-rw-r--r--test/ruby/test_float.rb18
-rw-r--r--test/ruby/test_hash.rb13
-rw-r--r--test/ruby/test_io.rb12
-rw-r--r--test/ruby/test_time_tz.rb23
-rw-r--r--test/rubygems/test_gem_source_git.rb5
-rw-r--r--test/test_time.rb9
-rw-r--r--test/uri/test_common.rb11
-rw-r--r--test/uri/test_parser.rb7
-rw-r--r--test/zlib/test_zlib.rb65
-rw-r--r--thread.c4
-rw-r--r--tool/fake.rb1
-rw-r--r--tool/gem-unpack.rb1
-rw-r--r--tool/lib/test/unit/core_assertions.rb33
-rw-r--r--version.h10
-rw-r--r--vm_method.c9
63 files changed, 749 insertions, 212 deletions
diff --git a/.github/workflows/check_branch.yml b/.github/workflows/check_branch.yml
index 40292838f2..5bc20a5541 100644
--- a/.github/workflows/check_branch.yml
+++ b/.github/workflows/check_branch.yml
@@ -10,7 +10,7 @@ name: Pull Request
on: [pull_request]
jobs:
check_branch:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- name: Check if branch is ruby_2_7
run: |
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 6cdbdc272b..357be970a4 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -19,17 +19,9 @@ jobs:
run: |
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
- # Not using official actions/checkout because it's unstable and sometimes doesn't work for a fork.
- - name: Checkout ruby
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${GITHUB_REF#refs/heads/} https://github.com/${{ github.repository }} src
- git -C src reset --hard "$GITHUB_SHA"
- if: github.event_name == 'push'
- - name: Checkout a pull request
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${{ github.event.pull_request.head.ref }} https://github.com/${{ github.event.pull_request.head.repo.full_name }} src
- git -C src reset --hard ${{ github.event.pull_request.head.sha }}
- if: github.event_name == 'pull_request'
+ - uses: actions/checkout@v2
+ with:
+ path: src
- run: ./src/tool/actions-commit-info.sh
id: commit_info
- name: Install libraries
@@ -44,7 +36,7 @@ jobs:
- name: Autoconf
run: |
cd src
- autoconf
+ autoreconf -i
- name: Configure
run: |
mkdir build
diff --git a/.github/workflows/mjit.yml b/.github/workflows/mjit.yml
index 5b662caa14..5dc02ccb75 100644
--- a/.github/workflows/mjit.yml
+++ b/.github/workflows/mjit.yml
@@ -13,7 +13,7 @@ jobs:
test_task: [ "check" ] # to make job names consistent
jit_opts: [ "--jit", "--jit-wait" ]
fail-fast: false
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
if: "!contains(github.event.head_commit.message, '[ci skip]')"
steps:
- name: Install libraries
@@ -21,17 +21,9 @@ jobs:
set -x
sudo apt-get update -q || :
sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev bison autoconf ruby
- # Not using official actions/checkout because it's unstable and sometimes doesn't work for a fork.
- - name: Checkout ruby
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${GITHUB_REF#refs/heads/} https://github.com/${{ github.repository }} src
- git -C src reset --hard "$GITHUB_SHA"
- if: github.event_name == 'push'
- - name: Checkout a pull request
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${{ github.event.pull_request.head.ref }} https://github.com/${{ github.event.pull_request.head.repo.full_name }} src
- git -C src reset --hard ${{ github.event.pull_request.head.sha }}
- if: github.event_name == 'pull_request'
+ - uses: actions/checkout@v2
+ with:
+ path: src
- run: ./src/tool/actions-commit-info.sh
id: commit_info
- name: Fixed world writable dirs
@@ -42,7 +34,7 @@ jobs:
run: |
echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- name: Autoconf
- run: cd src && exec autoconf
+ run: cd src && exec autoreconf -i
- name: configure
run: |
mkdir build
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index 68f28d7b40..526fc47ce3 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
test_task: [ "check", "test-bundler", "test-bundled-gems" ]
- os: [ubuntu-latest, ubuntu-16.04]
+ os: [ubuntu-20.04]
exclude:
- test_task: test-bundler
os: ubuntu-16.04
@@ -52,17 +52,9 @@ jobs:
set -x
sudo apt-get update -q || :
sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev bison autoconf ruby
- # Not using official actions/checkout because it's unstable and sometimes doesn't work for a fork.
- - name: Checkout ruby
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${GITHUB_REF#refs/heads/} https://github.com/${{ github.repository }} src
- git -C src reset --hard "$GITHUB_SHA"
- if: github.event_name == 'push'
- - name: Checkout a pull request
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${{ github.event.pull_request.head.ref }} https://github.com/${{ github.event.pull_request.head.repo.full_name }} src
- git -C src reset --hard ${{ github.event.pull_request.head.sha }}
- if: github.event_name == 'pull_request'
+ - uses: actions/checkout@v2
+ with:
+ path: src
- run: ./src/tool/actions-commit-info.sh
id: commit_info
- name: Fixed world writable dirs
@@ -73,7 +65,7 @@ jobs:
run: |
echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- name: Autoconf
- run: cd src && exec autoconf
+ run: cd src && exec autoreconf -i
- name: configure
run: |
mkdir build
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 82cca9353b..265a8a6157 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -37,18 +37,9 @@ jobs:
- name: Install libraries with chocolatey
run: |
choco install --no-progress openssl winflexbison3
- # Not using official actions/checkout because it's unstable and sometimes doesn't work for a fork.
- - name: Checkout ruby
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${GITHUB_REF#refs/heads/} https://github.com/${{ github.repository }} src
- git -C src reset --hard ${{ github.sha }}
- if: github.event_name == 'push'
- shell: bash
- - name: Checkout a pull request
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${{ github.event.pull_request.head.ref }} https://github.com/${{ github.event.pull_request.head.repo.full_name }} src
- git -C src reset --hard ${{ github.event.pull_request.head.sha }}
- if: github.event_name == 'pull_request'
+ - uses: actions/checkout@v2
+ with:
+ path: src
- run: ./src/tool/actions-commit-info.sh
shell: bash
id: commit_info
diff --git a/appveyor.yml b/appveyor.yml
index 7909de9e6b..d13ec885d1 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,7 +5,7 @@ platform:
- x64
environment:
ruby_version: "24-%Platform%"
- zlib_version: "1.2.11"
+ zlib_version: "1.2.13"
matrix:
- build: vs
vs: 120
diff --git a/configure.ac b/configure.ac
index 826a688871..4395a2b156 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2729,6 +2729,14 @@ AS_IF([test "$with_dln_a_out" != yes], [
: ${LDFLAGS=""}
: ${LIBPATHENV=DYLD_FALLBACK_LIBRARY_PATH}
: ${PRELOADENV=DYLD_INSERT_LIBRARIES}
+ AS_IF([test x"$enable_shared" = xyes], [
+ # Resolve symbols from libruby.dylib when --enable-shared
+ EXTDLDFLAGS='$(LIBRUBYARG_SHARED)'
+ ], [test "x$EXTSTATIC" = x], [
+ # When building exts as bundles, a mach-o bundle needs to know its loader
+ # program to bind symbols from the ruby executable
+ EXTDLDFLAGS="-bundle_loader '\$(BUILTRUBY)'"
+ ])
rb_cv_dlopen=yes],
[aix*], [ : ${LDSHARED='$(CC)'}
AS_IF([test "$GCC" = yes], [
@@ -2765,15 +2773,26 @@ AS_IF([test "$with_dln_a_out" != yes], [
AS_IF([test "$rb_cv_dlopen" = yes], [
AS_CASE(["$target_os"],
[darwin*], [
+ AC_SUBST(ADDITIONAL_DLDFLAGS, "")
for flag in \
- "-undefined dynamic_lookup" \
"-multiply_defined suppress" \
+ "-undefined dynamic_lookup" \
; do
- test "x${linker_flag}" = x || flag="${linker_flag}`echo ${flag} | tr ' ' ,`"
- RUBY_TRY_LDFLAGS([$flag], [], [flag=])
- AS_IF([test "x$flag" != x], [
- RUBY_APPEND_OPTIONS(DLDFLAGS, [$flag])
- ])
+ test "x${linker_flag}" = x || flag="${linker_flag}`echo ${flag} | tr ' ' ,`"
+ RUBY_TRY_LDFLAGS([$flag], [], [$flag=])
+ AS_IF([test x"$flag" = x], [continue])
+
+ AC_MSG_CHECKING([whether $flag is accepted for bundle])
+ : > conftest.c
+ AS_IF([${LDSHARED/'$(CC)'/$CC} -o conftest.bundle $flag conftest.c >/dev/null 2>conftest.err &&
+ test ! -s conftest.err], [
+ AC_MSG_RESULT([yes])
+ RUBY_APPEND_OPTIONS(DLDFLAGS, [$flag])
+ ], [
+ AC_MSG_RESULT([no])
+ RUBY_APPEND_OPTIONS(ADDITIONAL_DLDFLAGS, [$flag])
+ ])
+ rm -fr conftest.*
done
])
])
diff --git a/cont.c b/cont.c
index 7f971a9e9d..f1edd82bf0 100644
--- a/cont.c
+++ b/cont.c
@@ -1796,7 +1796,7 @@ rb_fiber_new(rb_block_call_func_t func, VALUE obj)
return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), &shared_fiber_pool);
}
-static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt);
+NORETURN(static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt));
#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? RB_PASS_EMPTY_KEYWORDS : rb_keyword_given_p())
@@ -2090,6 +2090,7 @@ rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt)
next_fiber = return_fiber();
if (need_interrupt) RUBY_VM_SET_INTERRUPT(&next_fiber->cont.saved_ec);
fiber_switch(next_fiber, 1, &value, 0, RB_NO_KEYWORDS);
+ ruby_stop(0);
}
VALUE
diff --git a/enc/Makefile.in b/enc/Makefile.in
index 8385236494..c389c24825 100644
--- a/enc/Makefile.in
+++ b/enc/Makefile.in
@@ -20,6 +20,7 @@ TRANSSODIR = $(ENCSODIR)/trans
DLEXT = @DLEXT@
OBJEXT = @OBJEXT@
LIBEXT = @LIBEXT@
+EXEEXT = @EXEEXT@
TIMESTAMPDIR = $(EXTOUT)/.timestamp
ENC_TRANS_D = $(TIMESTAMPDIR)/.enc-trans.time
ENC_TRANS_SO_D = $(TIMESTAMPDIR)/.enc-trans.so.time
@@ -33,6 +34,7 @@ RUBY_SO_NAME = @RUBY_SO_NAME@
LIBRUBY = @LIBRUBY@
LIBRUBYARG_SHARED = @LIBRUBYARG_SHARED@
LIBRUBYARG_STATIC = $(LIBRUBYARG_SHARED)
+BUILTRUBY = $(topdir)/miniruby$(EXEEXT)
empty =
AR = @AR@
diff --git a/ext/extmk.rb b/ext/extmk.rb
index 80a0a1208d..97f1ad9c39 100755
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -408,8 +408,10 @@ if CROSS_COMPILING
$ruby = $mflags.defined?("MINIRUBY") || CONFIG['MINIRUBY']
elsif sep = config_string('BUILD_FILE_SEPARATOR')
$ruby = "$(topdir:/=#{sep})#{sep}miniruby" + EXEEXT
-else
+elsif CONFIG['EXTSTATIC']
$ruby = '$(topdir)/miniruby' + EXEEXT
+else
+ $ruby = '$(topdir)/ruby' + EXEEXT
end
$ruby = [$ruby]
$ruby << "-I'$(topdir)'"
@@ -421,6 +423,7 @@ end
topruby = $ruby
$ruby = topruby.join(' ')
$mflags << "ruby=#$ruby"
+$builtruby = '$(topdir)/miniruby' + EXEEXT # Must be an executable path
MTIMES = [__FILE__, 'rbconfig.rb', srcdir+'/lib/mkmf.rb'].collect {|f| File.mtime(f)}
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index 9e7ee53397..99b268182a 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -1,3 +1,13 @@
+Version 2.1.4
+=============
+
+Bug fixes
+---------
+
+* Do not use pkg-config if --with-openssl-dir option is specified.
+ [[GitHub #486]](https://github.com/ruby/openssl/pull/486)
+
+
Version 2.1.3
=============
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 7e817ae2da..f4212bd450 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -14,7 +14,7 @@
require "mkmf"
require File.expand_path('../deprecation', __FILE__)
-dir_config("openssl")
+dir_config_given = dir_config("openssl").any?
dir_config("kerberos")
Logging::message "=== OpenSSL for Ruby configurator ===\n"
@@ -88,7 +88,7 @@ def find_openssl_library
end
Logging::message "=== Checking for required stuff... ===\n"
-pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h")
+pkg_config_found = !dir_config_given && pkg_config("openssl") && have_header("openssl/ssl.h")
if !pkg_config_found && !find_openssl_library
Logging::message "=== Checking for required stuff failed. ===\n"
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index c22eece7d6..82a91f4173 100644
--- a/ext/openssl/openssl.gemspec
+++ b/ext/openssl/openssl.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "openssl"
- spec.version = "2.1.3"
+ spec.version = "2.1.4"
spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
spec.email = ["ruby-core@ruby-lang.org"]
spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.}
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.3.0"
spec.add_runtime_dependency "ipaddr"
- spec.add_development_dependency "rake"
+ spec.add_development_dependency "rake", ">= 11.2.0"
spec.add_development_dependency "rake-compiler"
spec.add_development_dependency "test-unit", "~> 3.0"
spec.add_development_dependency "rdoc"
diff --git a/ext/openssl/ossl_version.h b/ext/openssl/ossl_version.h
index edbd8ce3fa..70182a71e7 100644
--- a/ext/openssl/ossl_version.h
+++ b/ext/openssl/ossl_version.h
@@ -10,6 +10,6 @@
#if !defined(_OSSL_VERSION_H_)
#define _OSSL_VERSION_H_
-#define OSSL_VERSION "2.1.3"
+#define OSSL_VERSION "2.1.4"
#endif /* _OSSL_VERSION_H_ */
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 5c8aab24af..82e9fc42da 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -285,6 +285,7 @@ static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
* - Zlib::MemError
* - Zlib::BufError
* - Zlib::VersionError
+ * - Zlib::InProgressError
*
* (if you have GZIP_SUPPORT)
* - Zlib::GzipReader
@@ -301,7 +302,7 @@ void Init_zlib(void);
/*--------- Exceptions --------*/
static VALUE cZError, cStreamEnd, cNeedDict;
-static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
+static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError, cInProgressError;
static void
raise_zlib_error(int err, const char *msg)
@@ -530,6 +531,7 @@ struct zstream {
unsigned long flags;
VALUE buf;
VALUE input;
+ VALUE mutex;
z_stream stream;
const struct zstream_funcs {
int (*reset)(z_streamp);
@@ -538,13 +540,14 @@ struct zstream {
} *func;
};
-#define ZSTREAM_FLAG_READY 0x1
-#define ZSTREAM_FLAG_IN_STREAM 0x2
-#define ZSTREAM_FLAG_FINISHED 0x4
-#define ZSTREAM_FLAG_CLOSING 0x8
-#define ZSTREAM_FLAG_GZFILE 0x10 /* disallows yield from expand_buffer for
+#define ZSTREAM_FLAG_READY (1 << 0)
+#define ZSTREAM_FLAG_IN_STREAM (1 << 1)
+#define ZSTREAM_FLAG_FINISHED (1 << 2)
+#define ZSTREAM_FLAG_CLOSING (1 << 3)
+#define ZSTREAM_FLAG_GZFILE (1 << 4) /* disallows yield from expand_buffer for
gzip*/
-#define ZSTREAM_FLAG_UNUSED 0x20
+#define ZSTREAM_IN_PROGRESS (1 << 5)
+#define ZSTREAM_FLAG_UNUSED (1 << 6)
#define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
#define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
@@ -571,7 +574,9 @@ static const struct zstream_funcs inflate_funcs = {
};
struct zstream_run_args {
- struct zstream * z;
+ struct zstream *const z;
+ Bytef *src;
+ long len;
int flush; /* stream flush value for inflate() or deflate() */
int interrupt; /* stop processing the stream and return to ruby */
int jump_state; /* for buffer expansion block break or exception */
@@ -602,6 +607,7 @@ zstream_init(struct zstream *z, const struct zstream_funcs *func)
z->flags = 0;
z->buf = Qnil;
z->input = Qnil;
+ z->mutex = rb_mutex_new();
z->stream.zalloc = zlib_mem_alloc;
z->stream.zfree = zlib_mem_free;
z->stream.opaque = Z_NULL;
@@ -631,7 +637,9 @@ zstream_expand_buffer(struct zstream *z)
rb_obj_reveal(z->buf, rb_cString);
+ rb_mutex_unlock(z->mutex);
rb_protect(rb_yield, z->buf, &state);
+ rb_mutex_lock(z->mutex);
z->buf = Qnil;
zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
@@ -1024,19 +1032,18 @@ zstream_unblock_func(void *ptr)
args->interrupt = 1;
}
-static void
-zstream_run(struct zstream *z, Bytef *src, long len, int flush)
+static VALUE
+zstream_run_try(VALUE value_arg)
{
- struct zstream_run_args args;
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+ struct zstream *z = args->z;
+ Bytef *src = args->src;
+ long len = args->len;
+ int flush = args->flush;
+
int err;
VALUE old_input = Qnil;
- args.z = z;
- args.flush = flush;
- args.interrupt = 0;
- args.jump_state = 0;
- args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p();
-
if (NIL_P(z->input) && len == 0) {
z->stream.next_in = (Bytef*)"";
z->stream.avail_in = 0;
@@ -1058,14 +1065,20 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush)
loop:
#ifndef RB_NOGVL_UBF_ASYNC_SAFE
- err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
- zstream_unblock_func, (void *)&args);
+ err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)args,
+ zstream_unblock_func, (void *)args);
#else
- err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args,
- zstream_unblock_func, (void *)&args,
+ err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)args,
+ zstream_unblock_func, (void *)args,
RB_NOGVL_UBF_ASYNC_SAFE);
#endif
+ /* retry if no exception is thrown */
+ if (err == Z_OK && args->interrupt) {
+ args->interrupt = 0;
+ goto loop;
+ }
+
if (flush != Z_FINISH && err == Z_BUF_ERROR
&& z->stream.avail_out > 0) {
z->flags |= ZSTREAM_FLAG_IN_STREAM;
@@ -1099,10 +1112,52 @@ loop:
rb_gc_force_recycle(old_input);
}
- if (args.jump_state)
- rb_jump_tag(args.jump_state);
+ if (args->jump_state)
+ rb_jump_tag(args->jump_state);
+ return Qnil;
+}
+
+static VALUE
+zstream_run_ensure(VALUE value_arg)
+{
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+
+ /* Remove ZSTREAM_IN_PROGRESS flag to signal that this zstream is not in use. */
+ args->z->flags &= ~ZSTREAM_IN_PROGRESS;
+
+ return Qnil;
+}
+
+static VALUE
+zstream_run_synchronized(VALUE value_arg)
+{
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+
+ /* Cannot start zstream while it is in progress. */
+ if (args->z->flags & ZSTREAM_IN_PROGRESS) {
+ rb_raise(cInProgressError, "zlib stream is in progress");
+ }
+ args->z->flags |= ZSTREAM_IN_PROGRESS;
+
+ rb_ensure(zstream_run_try, value_arg, zstream_run_ensure, value_arg);
+
+ return Qnil;
}
+static void
+zstream_run(struct zstream *z, Bytef *src, long len, int flush)
+{
+ struct zstream_run_args args = {
+ .z = z,
+ .src = src,
+ .len = len,
+ .flush = flush,
+ .interrupt = 0,
+ .jump_state = 0,
+ .stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p(),
+ };
+ rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&args);
+}
static VALUE
zstream_sync(struct zstream *z, Bytef *src, long len)
{
@@ -1148,6 +1203,7 @@ zstream_mark(void *p)
struct zstream *z = p;
rb_gc_mark(z->buf);
rb_gc_mark(z->input);
+ rb_gc_mark(z->mutex);
}
static void
@@ -4471,6 +4527,7 @@ Init_zlib(void)
cMemError = rb_define_class_under(mZlib, "MemError", cZError);
cBufError = rb_define_class_under(mZlib, "BufError", cZError);
cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
+ cInProgressError = rb_define_class_under(mZlib, "InProgressError", cZError);
rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
@@ -4778,6 +4835,7 @@ Init_zlib(void)
* - Zlib::MemError
* - Zlib::BufError
* - Zlib::VersionError
+ * - Zlib::InProgressError
*
*/
@@ -4853,6 +4911,20 @@ Init_zlib(void)
*/
/*
+ * Document-class: Zlib::InProgressError
+ *
+ * Subclass of Zlib::Error. This error is raised when the zlib
+ * stream is currently in progress.
+ *
+ * For example:
+ *
+ * inflater = Zlib::Inflate.new
+ * inflater.inflate(compressed) do
+ * inflater.inflate(compressed) # Raises Zlib::InProgressError
+ * end
+ */
+
+/*
* Document-class: Zlib::GzipFile::Error
*
* Base class of errors that occur when processing GZIP files.
diff --git a/file.c b/file.c
index a7cf696c10..455e1182e7 100644
--- a/file.c
+++ b/file.c
@@ -253,6 +253,46 @@ rb_str_encode_ospath(VALUE path)
#ifdef __APPLE__
# define NORMALIZE_UTF8PATH 1
+
+# ifdef HAVE_WORKING_FORK
+static void
+rb_CFString_class_initialize_before_fork(void)
+{
+ /*
+ * Since macOS 13, CFString family API used in
+ * rb_str_append_normalized_ospath may internally use Objective-C classes
+ * (NSTaggedPointerString and NSPlaceholderMutableString) for small strings.
+ *
+ * On the other hand, Objective-C classes should not be used for the first
+ * time in a fork()'ed but not exec()'ed process. Violations for this rule
+ * can result deadlock during class initialization, so Objective-C runtime
+ * conservatively crashes on such cases by default.
+ *
+ * Therefore, we need to use CFString API to initialize Objective-C classes
+ * used internally *before* fork().
+ *
+ * For future changes, please note that this initialization process cannot
+ * be done in ctor because NSTaggedPointerString in CoreFoundation is enabled
+ * after CFStringInitializeTaggedStrings(), which is called during loading
+ * Objective-C runtime after ctor.
+ * For more details, see https://bugs.ruby-lang.org/issues/18912
+ */
+
+ /* Enough small but non-empty ASCII string to fit in NSTaggedPointerString. */
+ const char small_str[] = "/";
+ long len = sizeof(small_str) - 1;
+
+ const CFAllocatorRef alloc = kCFAllocatorDefault;
+ CFStringRef s = CFStringCreateWithBytesNoCopy(alloc,
+ (const UInt8 *)small_str,
+ len, kCFStringEncodingUTF8,
+ FALSE, kCFAllocatorNull);
+ CFMutableStringRef m = CFStringCreateMutableCopy(alloc, len, s);
+ CFRelease(m);
+ CFRelease(s);
+}
+# endif
+
static VALUE
rb_str_append_normalized_ospath(VALUE str, const char *ptr, long len)
{
@@ -6455,6 +6495,10 @@ const char ruby_null_device[] =
void
Init_File(void)
{
+#if defined(__APPLE__) && defined(HAVE_WORKING_FORK)
+ rb_CFString_class_initialize_before_fork();
+#endif
+
VALUE separator;
rb_mFileTest = rb_define_module("FileTest");
diff --git a/io.c b/io.c
index 4d32e2ee3b..be6c6b637f 100644
--- a/io.c
+++ b/io.c
@@ -11022,6 +11022,13 @@ nogvl_fcopyfile(struct copy_stream_struct *stp)
return 0;
if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
return 0;
+ if (fcntl(stp->dst_fd, F_GETFL) & O_APPEND) {
+ /* fcopyfile(3) appends src IO to dst IO and then truncates
+ * dst IO to src IO's original size. */
+ off_t end = lseek(stp->dst_fd, 0, SEEK_END);
+ lseek(stp->dst_fd, 0, SEEK_SET);
+ if (end > (off_t)0) return 0;
+ }
if (src_offset > (off_t)0) {
off_t r;
diff --git a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
index 07ef4391c0..bc7c9c8568 100644
--- a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
+++ b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
@@ -3,8 +3,8 @@ module Bundler::URI
class RFC3986_Parser # :nodoc:
# Bundler::URI defined in RFC3986
# this regexp is modified not to host is not empty string
- RFC3986_URI = /\A(?<Bundler::URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
- RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+)\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])+)(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
+ RFC3986_URI = /\A(?<Bundler::URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*+):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])++))?(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
+ RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])++))?(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])++)(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
attr_reader :regexp
def initialize
diff --git a/lib/bundler/vendor/uri/lib/uri/version.rb b/lib/bundler/vendor/uri/lib/uri/version.rb
index 56177ef194..c162bf6368 100644
--- a/lib/bundler/vendor/uri/lib/uri/version.rb
+++ b/lib/bundler/vendor/uri/lib/uri/version.rb
@@ -1,6 +1,6 @@
module Bundler::URI
# :stopdoc:
- VERSION_CODE = '001000'.freeze
+ VERSION_CODE = '00100002'.freeze
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
# :startdoc:
end
diff --git a/lib/cgi/cookie.rb b/lib/cgi/cookie.rb
index 6b0d89ca3b..1a9c1a82c1 100644
--- a/lib/cgi/cookie.rb
+++ b/lib/cgi/cookie.rb
@@ -40,6 +40,10 @@ class CGI
class Cookie < Array
@@accept_charset="UTF-8" unless defined?(@@accept_charset)
+ TOKEN_RE = %r"\A[[!-~]&&[^()<>@,;:\\\"/?=\[\]{}]]+\z"
+ PATH_VALUE_RE = %r"\A[[ -~]&&[^;]]*\z"
+ DOMAIN_VALUE_RE = %r"\A(?<label>(?!-)[-A-Za-z0-9]+(?<!-))(?:\.\g<label>)*\z"
+
# Create a new CGI::Cookie object.
#
# :call-seq:
@@ -72,8 +76,8 @@ class CGI
@domain = nil
@expires = nil
if name.kind_of?(String)
- @name = name
- @path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
+ self.name = name
+ self.path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
@secure = false
@httponly = false
return super(value)
@@ -84,11 +88,11 @@ class CGI
raise ArgumentError, "`name' required"
end
- @name = options["name"]
+ self.name = options["name"]
value = Array(options["value"])
# simple support for IE
- @path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
- @domain = options["domain"]
+ self.path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
+ self.domain = options["domain"]
@expires = options["expires"]
@secure = options["secure"] == true
@httponly = options["httponly"] == true
@@ -97,11 +101,35 @@ class CGI
end
# Name of this cookie, as a +String+
- attr_accessor :name
+ attr_reader :name
+ # Set name of this cookie
+ def name=(str)
+ if str and !TOKEN_RE.match?(str)
+ raise ArgumentError, "invalid name: #{str.dump}"
+ end
+ @name = str
+ end
+
# Path for which this cookie applies, as a +String+
- attr_accessor :path
+ attr_reader :path
+ # Set path for which this cookie applies
+ def path=(str)
+ if str and !PATH_VALUE_RE.match?(str)
+ raise ArgumentError, "invalid path: #{str.dump}"
+ end
+ @path = str
+ end
+
# Domain for which this cookie applies, as a +String+
- attr_accessor :domain
+ attr_reader :domain
+ # Set domain for which this cookie applies
+ def domain=(str)
+ if str and ((str = str.b).bytesize > 255 or !DOMAIN_VALUE_RE.match?(str))
+ raise ArgumentError, "invalid domain: #{str.dump}"
+ end
+ @domain = str
+ end
+
# Time at which this cookie expires, as a +Time+
attr_accessor :expires
# True if this cookie is secure; false otherwise
diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
index bec76e0749..62e606837a 100644
--- a/lib/cgi/core.rb
+++ b/lib/cgi/core.rb
@@ -188,17 +188,28 @@ class CGI
# Using #header with the HTML5 tag maker will create a <header> element.
alias :header :http_header
+ def _no_crlf_check(str)
+ if str
+ str = str.to_s
+ raise "A HTTP status or header field must not include CR and LF" if str =~ /[\r\n]/
+ str
+ else
+ nil
+ end
+ end
+ private :_no_crlf_check
+
def _header_for_string(content_type) #:nodoc:
buf = ''.dup
if nph?()
- buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
+ buf << "#{_no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'} 200 OK#{EOL}"
buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
- buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}"
+ buf << "Server: #{_no_crlf_check($CGI_ENV['SERVER_SOFTWARE'])}#{EOL}"
buf << "Connection: close#{EOL}"
end
- buf << "Content-Type: #{content_type}#{EOL}"
+ buf << "Content-Type: #{_no_crlf_check(content_type)}#{EOL}"
if @output_cookies
- @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" }
end
return buf
end # _header_for_string
@@ -213,9 +224,9 @@ class CGI
## NPH
options.delete('nph') if defined?(MOD_RUBY)
if options.delete('nph') || nph?()
- protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
+ protocol = _no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'
status = options.delete('status')
- status = HTTP_STATUS[status] || status || '200 OK'
+ status = HTTP_STATUS[status] || _no_crlf_check(status) || '200 OK'
buf << "#{protocol} #{status}#{EOL}"
buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
@@ -223,38 +234,38 @@ class CGI
end
## common headers
status = options.delete('status')
- buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status
+ buf << "Status: #{HTTP_STATUS[status] || _no_crlf_check(status)}#{EOL}" if status
server = options.delete('server')
- buf << "Server: #{server}#{EOL}" if server
+ buf << "Server: #{_no_crlf_check(server)}#{EOL}" if server
connection = options.delete('connection')
- buf << "Connection: #{connection}#{EOL}" if connection
+ buf << "Connection: #{_no_crlf_check(connection)}#{EOL}" if connection
type = options.delete('type')
- buf << "Content-Type: #{type}#{EOL}" #if type
+ buf << "Content-Type: #{_no_crlf_check(type)}#{EOL}" #if type
length = options.delete('length')
- buf << "Content-Length: #{length}#{EOL}" if length
+ buf << "Content-Length: #{_no_crlf_check(length)}#{EOL}" if length
language = options.delete('language')
- buf << "Content-Language: #{language}#{EOL}" if language
+ buf << "Content-Language: #{_no_crlf_check(language)}#{EOL}" if language
expires = options.delete('expires')
buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
## cookie
if cookie = options.delete('cookie')
case cookie
when String, Cookie
- buf << "Set-Cookie: #{cookie}#{EOL}"
+ buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}"
when Array
arr = cookie
- arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
+ arr.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
when Hash
hash = cookie
- hash.each_value {|c| buf << "Set-Cookie: #{c}#{EOL}" }
+ hash.each_value {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
end
end
if @output_cookies
- @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
+ @output_cookies.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
end
## other headers
options.each do |key, value|
- buf << "#{key}: #{value}#{EOL}"
+ buf << "#{_no_crlf_check(key)}: #{_no_crlf_check(value)}#{EOL}"
end
return buf
end # _header_for_hash
diff --git a/lib/cgi/version.rb b/lib/cgi/version.rb
index e145a762c6..ee0c748069 100644
--- a/lib/cgi/version.rb
+++ b/lib/cgi/version.rb
@@ -1,3 +1,3 @@
class CGI
- VERSION = "0.1.0.1"
+ VERSION = "0.1.0.2"
end
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index eabccd48eb..27bc9e5986 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -2034,6 +2034,11 @@ sitearch = #{CONFIG['sitearch']}
ruby_version = #{RbConfig::CONFIG['ruby_version']}
ruby = #{$ruby.sub(%r[\A#{Regexp.quote(RbConfig::CONFIG['bindir'])}(?=/|\z)]) {'$(bindir)'}}
RUBY = $(ruby#{sep})
+BUILTRUBY = #{if defined?($builtruby) && $builtruby
+ $builtruby
+ else
+ File.join('$(bindir)', CONFIG["RUBY_INSTALL_NAME"] + CONFIG['EXEEXT'])
+ end}
ruby_headers = #{headers.join(' ')}
RM = #{config_string('RM', &possible_command) || '$(RUBY) -run -e rm -- -f'}
@@ -2552,6 +2557,7 @@ site-install-rb: install-rb
$INCFLAGS << " -I$(hdrdir)/ruby/backward" unless $extmk
$INCFLAGS << " -I$(hdrdir) -I$(srcdir)"
$DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
+ config_string("ADDITIONAL_DLDFLAGS") {|flags| $DLDFLAGS << " " << flags} unless $extmk
$LIBEXT = config['LIBEXT'].dup
$OBJEXT = config["OBJEXT"].dup
$EXEEXT = config["EXEEXT"].dup
diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb
index 8641be4eae..b99cf17c32 100644
--- a/lib/net/http/header.rb
+++ b/lib/net/http/header.rb
@@ -9,6 +9,8 @@
# convenient formats.
#
module Net::HTTPHeader
+ MAX_KEY_LENGTH = 1024
+ MAX_FIELD_LENGTH = 65536
def initialize_http_header(initheader)
@header = {}
@@ -19,6 +21,12 @@ module Net::HTTPHeader
warn "net/http: nil HTTP header: #{key}", uplevel: 3 if $VERBOSE
else
value = value.strip # raise error for invalid byte sequences
+ if key.to_s.bytesize > MAX_KEY_LENGTH
+ raise ArgumentError, "too long (#{key.bytesize} bytes) header: #{key[0, 30].inspect}..."
+ end
+ if value.to_s.bytesize > MAX_FIELD_LENGTH
+ raise ArgumentError, "header #{key} has too long field vallue: #{value.bytesize}"
+ end
if value.count("\r\n") > 0
raise ArgumentError, "header #{key} has field value #{value.inspect}, this cannot include CR/LF"
end
diff --git a/lib/time.rb b/lib/time.rb
index f27bacde65..245e1a2320 100644
--- a/lib/time.rb
+++ b/lib/time.rb
@@ -501,8 +501,8 @@ class Time
(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+
(\d{2,})\s+
(\d{2})\s*
- :\s*(\d{2})\s*
- (?::\s*(\d{2}))?\s+
+ :\s*(\d{2})
+ (?:\s*:\s*(\d\d))?\s+
([+-]\d{4}|
UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-IK-Z])/ix =~ date
# Since RFC 2822 permit comments, the regexp has no right anchor.
diff --git a/lib/uri/rfc3986_parser.rb b/lib/uri/rfc3986_parser.rb
index 08539f069a..c6f40a2dfc 100644
--- a/lib/uri/rfc3986_parser.rb
+++ b/lib/uri/rfc3986_parser.rb
@@ -3,8 +3,8 @@ module URI
class RFC3986_Parser # :nodoc:
# URI defined in RFC3986
# this regexp is modified not to host is not empty string
- RFC3986_URI = /\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
- RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+)\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])+)(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
+ RFC3986_URI = /\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*+):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])++))?(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
+ RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])++))?(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])++)(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
attr_reader :regexp
def initialize
diff --git a/lib/uri/version.rb b/lib/uri/version.rb
index 4f54113393..c07f8c2878 100644
--- a/lib/uri/version.rb
+++ b/lib/uri/version.rb
@@ -1,6 +1,6 @@
module URI
# :stopdoc:
- VERSION_CODE = '001000'.freeze
+ VERSION_CODE = '00100002'.freeze
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
# :startdoc:
end
diff --git a/load.c b/load.c
index 2441acfded..51c21ee4f2 100644
--- a/load.c
+++ b/load.c
@@ -1076,7 +1076,7 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
if (ftptr) load_unlock(RSTRING_PTR(path), !state);
if (state) {
- if (state == TAG_FATAL) {
+ if (state == TAG_FATAL || state == TAG_THROW) {
EC_JUMP_TAG(ec, state);
}
else if (exception) {
diff --git a/method.h b/method.h
index b26caaa92d..18deea7b03 100644
--- a/method.h
+++ b/method.h
@@ -164,6 +164,7 @@ struct rb_method_definition_struct {
BITFIELD(rb_method_type_t, type, VM_METHOD_TYPE_MINIMUM_BITS);
int alias_count : 28;
int complemented_count : 28;
+ unsigned int no_redef_warning: 1;
union {
rb_method_iseq_t iseq;
diff --git a/missing/dtoa.c b/missing/dtoa.c
index cbee13ee81..e82b60c2ce 100644
--- a/missing/dtoa.c
+++ b/missing/dtoa.c
@@ -1500,6 +1500,7 @@ break2:
if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
if (*s == '0') {
while (*++s == '0');
+ if (!*s) goto ret;
s1 = strchr(hexdigit, *s);
}
if (s1 != NULL) {
@@ -1522,7 +1523,7 @@ break2:
for (; *s && (s1 = strchr(hexdigit, *s)); ++s) {
adj += aadj * ((s1 - hexdigit) & 15);
if ((aadj /= 16) == 0.0) {
- while (strchr(hexdigit, *++s));
+ while (*++s && strchr(hexdigit, *s));
break;
}
}
diff --git a/mjit_worker.c b/mjit_worker.c
index 95518883c6..f0b73be2d0 100644
--- a/mjit_worker.c
+++ b/mjit_worker.c
@@ -823,8 +823,15 @@ link_o_to_so(const char **o_files, const char *so_file)
NULL
};
- char **args = form_args(7, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS,
- options, o_files, CC_LIBS, CC_DLDFLAGS_ARGS, CC_LINKER_ARGS);
+# if defined(__MACH__)
+ extern VALUE rb_libruby_selfpath;
+ const char *loader_args[] = {"-bundle_loader", StringValuePtr(rb_libruby_selfpath), NULL};
+# else
+ const char *loader_args[] = {NULL};
+# endif
+
+ char **args = form_args(8, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS,
+ options, o_files, loader_args, CC_LIBS, CC_DLDFLAGS_ARGS, CC_LINKER_ARGS);
if (args == NULL)
return false;
diff --git a/numeric.c b/numeric.c
index 3da0f7f6b0..ea15625697 100644
--- a/numeric.c
+++ b/numeric.c
@@ -4565,6 +4565,7 @@ rb_fix_lshift(VALUE x, VALUE y)
long val, width;
val = NUM2LONG(x);
+ if (!val) return (rb_to_int(y), INT2FIX(0));
if (!FIXNUM_P(y))
return rb_big_lshift(rb_int2big(val), y);
width = FIX2LONG(y);
@@ -4611,6 +4612,7 @@ rb_fix_rshift(VALUE x, VALUE y)
long i, val;
val = FIX2LONG(x);
+ if (!val) return (rb_to_int(y), INT2FIX(0));
if (!FIXNUM_P(y))
return rb_big_rshift(rb_int2big(val), y);
i = FIX2LONG(y);
diff --git a/parse.y b/parse.y
index 2bf825a052..dffb8b2a5c 100644
--- a/parse.y
+++ b/parse.y
@@ -46,7 +46,6 @@
#define YYCALLOC(nelem, size) rb_parser_calloc(p, (nelem), (size))
#define YYFREE(ptr) rb_parser_free(p, (ptr))
#define YYFPRINTF rb_parser_printf
-#define YYPRINT(out, tok, val) parser_token_value_print(p, (tok), &(val))
#define YY_LOCATION_PRINT(File, loc) \
rb_parser_printf(p, "%d.%d-%d.%d", \
(loc).beg_pos.lineno, (loc).beg_pos.column,\
@@ -602,7 +601,6 @@ RUBY_SYMBOL_EXPORT_END
static void error_duplicate_pattern_variable(struct parser_params *p, ID id, const YYLTYPE *loc);
static void error_duplicate_pattern_key(struct parser_params *p, ID id, const YYLTYPE *loc);
-static void parser_token_value_print(struct parser_params *p, enum yytokentype type, const YYSTYPE *valp);
static ID formal_argument(struct parser_params*, ID);
static ID shadowing_lvar(struct parser_params*,ID);
static void new_bv(struct parser_params*,ID);
@@ -969,6 +967,35 @@ static int looking_at_eol_p(struct parser_params *p);
%expect 0
%define api.pure
%define parse.error verbose
+%printer {
+#ifndef RIPPER
+ rb_parser_printf(p, "%"PRIsVALUE, rb_id2str($$));
+#else
+ rb_parser_printf(p, "%"PRIsVALUE, RNODE($$)->nd_rval);
+#endif
+} tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL tOP_ASGN
+%printer {
+#ifndef RIPPER
+ rb_parser_printf(p, "%+"PRIsVALUE, $$->nd_lit);
+#else
+ rb_parser_printf(p, "%+"PRIsVALUE, get_value($$));
+#endif
+} tINTEGER tFLOAT tRATIONAL tIMAGINARY tSTRING_CONTENT tCHAR
+%printer {
+#ifndef RIPPER
+ rb_parser_printf(p, "$%ld", $$->nd_nth);
+#else
+ rb_parser_printf(p, "%"PRIsVALUE, $$);
+#endif
+} tNTH_REF
+%printer {
+#ifndef RIPPER
+ rb_parser_printf(p, "$%c", (int)$$->nd_nth);
+#else
+ rb_parser_printf(p, "%"PRIsVALUE, $$);
+#endif
+} tBACK_REF
+
%lex-param {struct parser_params *p}
%parse-param {struct parser_params *p}
%initial-action
@@ -10424,49 +10451,6 @@ rb_parser_set_location(struct parser_params *p, YYLTYPE *yylloc)
}
#endif /* !RIPPER */
-static void
-parser_token_value_print(struct parser_params *p, enum yytokentype type, const YYSTYPE *valp)
-{
- VALUE v;
-
- switch (type) {
- case tIDENTIFIER: case tFID: case tGVAR: case tIVAR:
- case tCONSTANT: case tCVAR: case tLABEL: case tOP_ASGN:
-#ifndef RIPPER
- v = rb_id2str(valp->id);
-#else
- v = valp->node->nd_rval;
-#endif
- rb_parser_printf(p, "%"PRIsVALUE, v);
- break;
- case tINTEGER: case tFLOAT: case tRATIONAL: case tIMAGINARY:
- case tSTRING_CONTENT: case tCHAR:
-#ifndef RIPPER
- v = valp->node->nd_lit;
-#else
- v = valp->val;
-#endif
- rb_parser_printf(p, "%+"PRIsVALUE, v);
- break;
- case tNTH_REF:
-#ifndef RIPPER
- rb_parser_printf(p, "$%ld", valp->node->nd_nth);
-#else
- rb_parser_printf(p, "%"PRIsVALUE, valp->val);
-#endif
- break;
- case tBACK_REF:
-#ifndef RIPPER
- rb_parser_printf(p, "$%c", (int)valp->node->nd_nth);
-#else
- rb_parser_printf(p, "%"PRIsVALUE, valp->val);
-#endif
- break;
- default:
- break;
- }
-}
-
static int
assignable0(struct parser_params *p, ID id, const char **err)
{
diff --git a/ruby.c b/ruby.c
index 7d8d8e38f5..bcdfb321a3 100644
--- a/ruby.c
+++ b/ruby.c
@@ -28,7 +28,7 @@
#ifdef __hpux
#include <sys/pstat.h>
#endif
-#if defined(LOAD_RELATIVE) && defined(HAVE_DLADDR)
+#if (defined(LOAD_RELATIVE) || defined(__MACH__)) && defined(HAVE_DLADDR)
#include <dlfcn.h>
#endif
@@ -501,7 +501,7 @@ str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
void ruby_init_loadpath(void);
-#if defined(LOAD_RELATIVE)
+#if defined(LOAD_RELATIVE) || defined(__MACH__)
static VALUE
runtime_libruby_path(void)
{
@@ -577,6 +577,10 @@ runtime_libruby_path(void)
#define INITIAL_LOAD_PATH_MARK rb_intern_const("@gem_prelude_index")
VALUE ruby_archlibdir_path, ruby_prefix_path;
+#if defined(__MACH__)
+// A path to libruby.dylib itself or where it's statically linked to.
+VALUE rb_libruby_selfpath;
+#endif
void
ruby_init_loadpath(void)
@@ -584,6 +588,14 @@ ruby_init_loadpath(void)
VALUE load_path, archlibdir = 0;
ID id_initial_load_path_mark;
const char *paths = ruby_initial_load_paths;
+#if defined(LOAD_RELATIVE) || defined(__MACH__)
+ VALUE libruby_path = runtime_libruby_path();
+# if defined(__MACH__)
+ rb_libruby_selfpath = libruby_path;
+ rb_gc_register_address(&rb_libruby_selfpath);
+# endif
+#endif
+
#if defined LOAD_RELATIVE
#if !defined ENABLE_MULTIARCH
# define RUBY_ARCH_PATH ""
@@ -597,7 +609,7 @@ ruby_init_loadpath(void)
size_t baselen;
const char *p;
- sopath = runtime_libruby_path();
+ sopath = libruby_path;
libpath = RSTRING_PTR(sopath);
p = strrchr(libpath, '/');
diff --git a/spec/bundler/cache/git_spec.rb b/spec/bundler/cache/git_spec.rb
index 75525d405b..8123c514b6 100644
--- a/spec/bundler/cache/git_spec.rb
+++ b/spec/bundler/cache/git_spec.rb
@@ -149,6 +149,9 @@ RSpec.describe "bundle cache with git" do
end
it "copies repository to vendor cache, including submodules" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_git "submodule", "1.0"
git = build_git "has_submodule", "1.0" do |s|
diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index 00f8e96625..c5ea2c202d 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -826,6 +826,9 @@ RSpec.describe "bundle install with git sources" do
end
it "ignores submodules if :submodule is not passed" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_git "submodule", "1.0"
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
@@ -846,6 +849,9 @@ RSpec.describe "bundle install with git sources" do
end
it "handles repos with submodules" do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_git "submodule", "1.0"
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
diff --git a/spec/bundler/update/git_spec.rb b/spec/bundler/update/git_spec.rb
index 752033c842..8a41ab86db 100644
--- a/spec/bundler/update/git_spec.rb
+++ b/spec/bundler/update/git_spec.rb
@@ -117,6 +117,9 @@ RSpec.describe "bundle update" do
describe "with submodules" do
before :each do
+ # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(*%W[git config --global protocol.file.allow always])
+
build_repo4 do
build_gem "submodule" do |s|
s.write "lib/submodule.rb", "puts 'GEM'"
diff --git a/spec/ruby/core/time/shared/local.rb b/spec/ruby/core/time/shared/local.rb
index 43f331c4c1..997b7186f1 100644
--- a/spec/ruby/core/time/shared/local.rb
+++ b/spec/ruby/core/time/shared/local.rb
@@ -6,6 +6,7 @@ describe :time_local, shared: true do
end
end
+=begin
platform_is_not :windows do
describe "timezone changes" do
it "correctly adjusts the timezone change to 'CEST' on 'Europe/Amsterdam'" do
@@ -16,6 +17,7 @@ describe :time_local, shared: true do
end
end
end
+=end
end
describe :time_local_10_arg, shared: true do
diff --git a/spec/ruby/library/cgi/cookie/name_spec.rb b/spec/ruby/library/cgi/cookie/name_spec.rb
index 14226824c8..326a43ade3 100644
--- a/spec/ruby/library/cgi/cookie/name_spec.rb
+++ b/spec/ruby/library/cgi/cookie/name_spec.rb
@@ -6,18 +6,18 @@ describe "CGI::Cookie#name" do
cookie = CGI::Cookie.new("test-cookie")
cookie.name.should == "test-cookie"
- cookie = CGI::Cookie.new("name" => "another cookie")
- cookie.name.should == "another cookie"
+ cookie = CGI::Cookie.new("name" => "another-cookie")
+ cookie.name.should == "another-cookie"
end
end
describe "CGI::Cookie#name=" do
it "sets self's expiration date" do
cookie = CGI::Cookie.new("test-cookie")
- cookie.name = "another name"
- cookie.name.should == "another name"
+ cookie.name = "another-name"
+ cookie.name.should == "another-name"
- cookie.name = "and one more"
- cookie.name.should == "and one more"
+ cookie.name = "and-one-more"
+ cookie.name.should == "and-one-more"
end
end
diff --git a/spec/ruby/library/cgi/cookie/parse_spec.rb b/spec/ruby/library/cgi/cookie/parse_spec.rb
index 90d2c3d148..d484c7bad9 100644
--- a/spec/ruby/library/cgi/cookie/parse_spec.rb
+++ b/spec/ruby/library/cgi/cookie/parse_spec.rb
@@ -6,16 +6,16 @@ describe "CGI::Cookie.parse" do
expected = { "test-cookie" => ["one", "two", "three"] }
CGI::Cookie.parse("test-cookie=one&two&three").should == expected
- expected = { "second cookie" => ["three", "four"], "first cookie" => ["one", "two"] }
- CGI::Cookie.parse("first cookie=one&two;second cookie=three&four").should == expected
+ expected = { "second-cookie" => ["three", "four"], "first-cookie" => ["one", "two"] }
+ CGI::Cookie.parse("first-cookie=one&two;second-cookie=three&four").should == expected
end
it "does not use , for cookie separators" do
expected = {
- "first cookie" => ["one", "two"],
- "second cookie" => ["three", "four,third_cookie=five", "six"]
+ "first-cookie" => ["one", "two"],
+ "second-cookie" => ["three", "four,third_cookie=five", "six"]
}
- CGI::Cookie.parse("first cookie=one&two;second cookie=three&four,third_cookie=five&six").should == expected
+ CGI::Cookie.parse("first-cookie=one&two;second-cookie=three&four,third_cookie=five&six").should == expected
end
it "unescapes the Cookie values" do
diff --git a/st.c b/st.c
index 4258f93ffc..599f93a463 100644
--- a/st.c
+++ b/st.c
@@ -1486,7 +1486,6 @@ st_shift(st_table *tab, st_data_t *key, st_data_t *value)
}
}
st_assert(tab->num_entries == 0);
- tab->entries_start = tab->entries_bound = 0;
if (value != 0) *value = 0;
return 0;
}
diff --git a/test/cgi/test_cgi_cookie.rb b/test/cgi/test_cgi_cookie.rb
index 985cc0d7a1..e3ec4bea52 100644
--- a/test/cgi/test_cgi_cookie.rb
+++ b/test/cgi/test_cgi_cookie.rb
@@ -60,6 +60,24 @@ class CGICookieTest < Test::Unit::TestCase
end
+ def test_cgi_cookie_new_with_domain
+ h = {'name'=>'name1', 'value'=>'value1'}
+ cookie = CGI::Cookie.new('domain'=>'a.example.com', **h)
+ assert_equal('a.example.com', cookie.domain)
+
+ cookie = CGI::Cookie.new('domain'=>'1.example.com', **h)
+ assert_equal('1.example.com', cookie.domain, 'enhanced by RFC 1123')
+
+ assert_raise(ArgumentError) {
+ CGI::Cookie.new('domain'=>'-a.example.com', **h)
+ }
+
+ assert_raise(ArgumentError) {
+ CGI::Cookie.new('domain'=>'a-.example.com', **h)
+ }
+ end
+
+
def test_cgi_cookie_scriptname
cookie = CGI::Cookie.new('name1', 'value1')
assert_equal('', cookie.path)
@@ -118,6 +136,70 @@ class CGICookieTest < Test::Unit::TestCase
end
+ def test_cgi_cookie_domain_injection_into_name
+ name = "a=b; domain=example.com;"
+ path = "/"
+ domain = "example.jp"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
+
+ def test_cgi_cookie_newline_injection_into_name
+ name = "a=b;\r\nLocation: http://example.com#"
+ path = "/"
+ domain = "example.jp"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
+
+ def test_cgi_cookie_multibyte_injection_into_name
+ name = "a=b;\u3042"
+ path = "/"
+ domain = "example.jp"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
+
+ def test_cgi_cookie_injection_into_path
+ name = "name"
+ path = "/; samesite=none"
+ domain = "example.jp"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
+
+ def test_cgi_cookie_injection_into_domain
+ name = "name"
+ path = "/"
+ domain = "example.jp; samesite=none"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
instance_methods.each do |method|
private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
diff --git a/test/cgi/test_cgi_header.rb b/test/cgi/test_cgi_header.rb
index bab2d0348a..ec2f4deb72 100644
--- a/test/cgi/test_cgi_header.rb
+++ b/test/cgi/test_cgi_header.rb
@@ -176,6 +176,14 @@ class CGIHeaderTest < Test::Unit::TestCase
end
+ def test_cgi_http_header_crlf_injection
+ cgi = CGI.new
+ assert_raise(RuntimeError) { cgi.http_header("text/xhtml\r\nBOO") }
+ assert_raise(RuntimeError) { cgi.http_header("type" => "text/xhtml\r\nBOO") }
+ assert_raise(RuntimeError) { cgi.http_header("status" => "200 OK\r\nBOO") }
+ assert_raise(RuntimeError) { cgi.http_header("location" => "text/xhtml\r\nBOO") }
+ end
+
instance_methods.each do |method|
private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb
index a740c21ae9..d084f10f79 100644
--- a/test/ripper/test_parser_events.rb
+++ b/test/ripper/test_parser_events.rb
@@ -1498,16 +1498,9 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def test_block_variables
- assert_equal("[fcall(proc,[],&block([],[void()]))]", parse("proc{|;y|}"))
- if defined?(Process::RLIMIT_AS)
- dir = File.dirname(__FILE__)
- as = 100 * 1024 * 1024 # 100MB
- as *= 2 if RubyVM::MJIT.enabled? # space for compiler
- assert_in_out_err(%W(-I#{dir} -rdummyparser),
- "Process.setrlimit(Process::RLIMIT_AS,#{as}); "\
- "puts DummyParser.new('proc{|;y|!y}').parse",
- ["[fcall(proc,[],&block([],[unary(!,ref(y))]))]"], [], '[ruby-dev:39423]')
- end
+ bug4159 = '[ruby-dev:39423]'
+ assert_equal("[fcall(proc,[],&block([],[void()]))]", parse("proc{|;y|}"), bug4159)
+ assert_equal("[fcall(proc,[],&block([],[unary(!,ref(y))]))]", parse("proc{|;y|!y}"), bug4159)
end
def test_unterminated_regexp
diff --git a/test/ruby/test_alias.rb b/test/ruby/test_alias.rb
index 33fb82e1d7..1acf12f7f3 100644
--- a/test/ruby/test_alias.rb
+++ b/test/ruby/test_alias.rb
@@ -227,4 +227,33 @@ class TestAlias < Test::Unit::TestCase
assert_equal(:foo, k.instance_method(:bar).original_name)
assert_equal(:foo, name)
end
+
+ def test_alias_suppressing_redefinition
+ assert_in_out_err(%w[-w], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class A
+ def foo; end
+ alias foo foo
+ def foo; end
+ end
+ end;
+ end
+
+ def test_alias_memory_leak
+ assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true)
+ begin;
+ class A
+ 500.times do
+ 1000.times do |i|
+ define_method(:"foo_#{i}") {}
+
+ alias :"foo_#{i}" :"foo_#{i}"
+
+ remove_method :"foo_#{i}"
+ end
+ GC.start
+ end
+ end
+ end;
+ end
end
diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb
index 9f6f19b669..ef732b9924 100644
--- a/test/ruby/test_enum.rb
+++ b/test/ruby/test_enum.rb
@@ -326,6 +326,17 @@ class TestEnumerable < Test::Unit::TestCase
empty.first
empty.block.call
end;
+
+ bug18475 = '[ruby-dev:107059]'
+ assert_in_out_err([], <<-'end;', [], /unexpected break/, bug18475)
+ e = Enumerator.new do |g|
+ Thread.new do
+ g << 1
+ end.join
+ end
+
+ e.first
+ end;
end
def test_sort
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 69bf7ebf0e..9efcfc76cf 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -181,6 +181,27 @@ class TestException < Test::Unit::TestCase
}
end
+ def test_catch_throw_in_require_cant_be_rescued
+ bug18562 = '[ruby-core:107403]'
+ Tempfile.create(["dep", ".rb"]) {|t|
+ t.puts("throw :extdep, 42")
+ t.close
+
+ rescue_all = Class.new(Exception)
+ def rescue_all.===(_)
+ raise "should not reach here"
+ end
+
+ v = assert_throw(:extdep, bug18562) do
+ require t.path
+ rescue rescue_all => e
+ assert(false, "should not reach here")
+ end
+
+ assert_equal(42, v, bug18562)
+ }
+ end
+
def test_throw_false
bug12743 = '[ruby-core:77229] [Bug #12743]'
Thread.start {
diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb
index a7ed9ac7e0..20436eca69 100644
--- a/test/ruby/test_fiber.rb
+++ b/test/ruby/test_fiber.rb
@@ -318,7 +318,7 @@ class TestFiber < Test::Unit::TestCase
Fiber.new {}.transfer
Fiber.new { Fiber.yield }
end
- exit!(0)
+ exit!(true)
end
}.transfer
_, status = Process.waitpid2(xpid)
@@ -327,8 +327,8 @@ class TestFiber < Test::Unit::TestCase
end.resume
end
pid, status = Process.waitpid2(pid)
- assert_equal(0, status.exitstatus, bug5700)
- assert_equal(false, status.signaled?, bug5700)
+ assert_not_predicate(status, :signaled?, bug5700)
+ assert_predicate(status, :success?, bug5700)
end
def test_exit_in_fiber
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index 7cbf3b5a8f..9c24dac8e6 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -171,6 +171,24 @@ class TestFloat < Test::Unit::TestCase
assert_raise(ArgumentError, n += z + "A") {Float(n)}
assert_raise(ArgumentError, n += z + ".0") {Float(n)}
end
+
+ x = nil
+ 2000.times do
+ x = Float("0x"+"0"*30)
+ break unless x == 0.0
+ end
+ assert_equal(0.0, x, ->{"%a" % x})
+ x = nil
+ 2000.times do
+ begin
+ x = Float("0x1."+"0"*270)
+ rescue ArgumentError => e
+ raise unless /"0x1\.0{270}"/ =~ e.message
+ else
+ break
+ end
+ end
+ assert_nil(x, ->{"%a" % x})
end
def test_divmod
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index 046ea40f5d..d4af130a07 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -983,6 +983,19 @@ class TestHash < Test::Unit::TestCase
assert_equal("FOO", h.shift)
end
+ def test_shift_for_empty_hash
+ # [ruby-dev:51159]
+ h = @cls[]
+ 100.times{|n|
+ while h.size < n
+ k = Random.rand 0..1<<30
+ h[k] = 1
+ end
+ 0 while h.shift
+ assert_equal({}, h)
+ }
+ end
+
def test_reject_bang2
assert_equal({1=>2}, @cls[1=>2,3=>4].reject! {|k, v| k + v == 7 })
assert_nil(@cls[1=>2,3=>4].reject! {|k, v| k == 5 })
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 1e4d88ef1e..37f1477483 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -440,6 +440,18 @@ class TestIO < Test::Unit::TestCase
}
end
+ def test_copy_stream_append_to_nonempty
+ with_srccontent("foobar") {|src, content|
+ preface = 'preface'
+ File.write('dst', preface)
+ File.open('dst', 'ab') do |dst|
+ ret = IO.copy_stream(src, dst)
+ assert_equal(content.bytesize, ret)
+ assert_equal(preface + content, File.read("dst"))
+ end
+ }
+ end
+
def test_copy_stream_smaller
with_srccontent {|src, content|
diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb
index 5ee12e4dbd..47f8c63077 100644
--- a/test/ruby/test_time_tz.rb
+++ b/test/ruby/test_time_tz.rb
@@ -7,9 +7,9 @@ class TestTimeTZ < Test::Unit::TestCase
has_lisbon_tz = true
force_tz_test = ENV["RUBY_FORCE_TIME_TZ_TEST"] == "yes"
case RUBY_PLATFORM
- when /linux/
+ when /darwin|linux/
force_tz_test = true
- when /darwin|freebsd|openbsd/
+ when /freebsd|openbsd/
has_lisbon_tz = false
force_tz_test = true
end
@@ -95,6 +95,9 @@ class TestTimeTZ < Test::Unit::TestCase
CORRECT_KIRITIMATI_SKIP_1994 = with_tz("Pacific/Kiritimati") {
Time.local(1994, 12, 31, 0, 0, 0).year == 1995
}
+ CORRECT_SINGAPORE_1982 = with_tz("Asia/Singapore") {
+ "2022g" if Time.local(1981, 12, 31, 23, 59, 59).utc_offset == 8*3600
+ }
def time_to_s(t)
t.to_s
@@ -140,9 +143,12 @@ class TestTimeTZ < Test::Unit::TestCase
def test_asia_singapore
with_tz(tz="Asia/Singapore") {
- assert_time_constructor(tz, "1981-12-31 23:59:59 +0730", :local, [1981,12,31,23,59,59])
- assert_time_constructor(tz, "1982-01-01 00:30:00 +0800", :local, [1982,1,1,0,0,0])
- assert_time_constructor(tz, "1982-01-01 00:59:59 +0800", :local, [1982,1,1,0,29,59])
+ assert_time_constructor(tz, "1981-12-31 23:29:59 +0730", :local, [1981,12,31,23,29,59])
+ if CORRECT_SINGAPORE_1982
+ assert_time_constructor(tz, "1982-01-01 00:00:00 +0800", :local, [1981,12,31,23,30,00])
+ assert_time_constructor(tz, "1982-01-01 00:00:00 +0800", :local, [1982,1,1,0,0,0])
+ assert_time_constructor(tz, "1982-01-01 00:29:59 +0800", :local, [1982,1,1,0,29,59])
+ end
assert_time_constructor(tz, "1982-01-01 00:30:00 +0800", :local, [1982,1,1,0,30,0])
}
end
@@ -196,7 +202,7 @@ class TestTimeTZ < Test::Unit::TestCase
def test_europe_lisbon
with_tz("Europe/Lisbon") {
- assert_equal("LMT", Time.new(-0x1_0000_0000_0000_0000).zone)
+ assert_include(%w"LMT CET", Time.new(-0x1_0000_0000_0000_0000).zone)
}
end if has_lisbon_tz
@@ -452,9 +458,12 @@ America/Managua Fri Jan 1 06:00:00 1993 UTC = Fri Jan 1 01:00:00 1993 EST isd
America/Managua Wed Jan 1 04:59:59 1997 UTC = Tue Dec 31 23:59:59 1996 EST isdst=0 gmtoff=-18000
America/Managua Wed Jan 1 05:00:00 1997 UTC = Tue Dec 31 23:00:00 1996 CST isdst=0 gmtoff=-21600
Asia/Singapore Sun Aug 8 16:30:00 1965 UTC = Mon Aug 9 00:00:00 1965 SGT isdst=0 gmtoff=27000
-Asia/Singapore Thu Dec 31 16:29:59 1981 UTC = Thu Dec 31 23:59:59 1981 SGT isdst=0 gmtoff=27000
+Asia/Singapore Thu Dec 31 15:59:59 1981 UTC = Thu Dec 31 23:29:59 1981 SGT isdst=0 gmtoff=27000
Asia/Singapore Thu Dec 31 16:30:00 1981 UTC = Fri Jan 1 00:30:00 1982 SGT isdst=0 gmtoff=28800
End
+ gen_zdump_test <<'End' if CORRECT_SINGAPORE_1982
+Asia/Singapore Thu Dec 31 16:00:00 1981 UTC = Fri Jan 1 00:00:00 1982 SGT isdst=0 gmtoff=28800
+End
gen_zdump_test CORRECT_TOKYO_DST_1951 ? <<'End' + (CORRECT_TOKYO_DST_1951 < "2018f" ? <<'2018e' : <<'2018f') : <<'End'
Asia/Tokyo Sat May 5 14:59:59 1951 UTC = Sat May 5 23:59:59 1951 JST isdst=0 gmtoff=32400
Asia/Tokyo Sat May 5 15:00:00 1951 UTC = Sun May 6 01:00:00 1951 JDT isdst=1 gmtoff=36000
diff --git a/test/rubygems/test_gem_source_git.rb b/test/rubygems/test_gem_source_git.rb
index 22fbdee05e..6d7b6b0383 100644
--- a/test/rubygems/test_gem_source_git.rb
+++ b/test/rubygems/test_gem_source_git.rb
@@ -64,6 +64,11 @@ class TestGemSourceGit < Gem::TestCase
end
def test_checkout_submodules
+ # We need to allow to checkout submodules with file:// protocol
+ # CVE-2022-39253
+ # https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(@git, *%W[config --global protocol.file.allow always])
+
source = Gem::Source::Git.new @name, @repository, 'master', true
git_gem 'b'
diff --git a/test/test_time.rb b/test/test_time.rb
index ca20788aac..4f11048596 100644
--- a/test/test_time.rb
+++ b/test/test_time.rb
@@ -62,6 +62,15 @@ class TestTimeExtension < Test::Unit::TestCase # :nodoc:
assert_equal(true, t.utc?)
end
+ def test_rfc2822_nonlinear
+ pre = ->(n) {"0 Feb 00 00 :00" + " " * n}
+ assert_linear_performance([100, 500, 5000, 50_000], pre: pre) do |s|
+ assert_raise(ArgumentError) do
+ Time.rfc2822(s)
+ end
+ end
+ end
+
def test_encode_rfc2822
t = Time.utc(1)
assert_equal("Mon, 01 Jan 0001 00:00:00 -0000", t.rfc2822)
diff --git a/test/uri/test_common.rb b/test/uri/test_common.rb
index 1afa35f93d..2b877c10d7 100644
--- a/test/uri/test_common.rb
+++ b/test/uri/test_common.rb
@@ -56,6 +56,17 @@ class TestCommon < Test::Unit::TestCase
assert_raise(NoMethodError) { Object.new.URI("http://www.ruby-lang.org/") }
end
+ def test_parse_timeout
+ pre = ->(n) {
+ 'https://example.com/dir/' + 'a' * (n * 100) + '/##.jpg'
+ }
+ assert_linear_performance((1..10).map {|i| i * 100}, pre: pre) do |uri|
+ assert_raise(URI::InvalidURIError) do
+ URI.parse(uri)
+ end
+ end
+ end
+
def test_encode_www_form_component
assert_equal("%00+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
"AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E",
diff --git a/test/uri/test_parser.rb b/test/uri/test_parser.rb
index b13a26ca84..37e7107bca 100644
--- a/test/uri/test_parser.rb
+++ b/test/uri/test_parser.rb
@@ -58,4 +58,11 @@ class URI::TestParser < Test::Unit::TestCase
assert_equal("\u3042", p1.unescape('%e3%81%82'.force_encoding(Encoding::US_ASCII)))
assert_equal("\xe3\x83\x90\xe3\x83\x90", p1.unescape("\xe3\x83\x90%e3%83%90"))
end
+
+ def test_split
+ assert_equal(["http", nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("http://example.com"))
+ assert_equal(["http", nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("http://[0::0]"))
+ assert_equal([nil, nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("//example.com"))
+ assert_equal([nil, nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("//[0::0]"))
+ end
end
diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb
index 7d703d15e4..e2cb4e3755 100644
--- a/test/zlib/test_zlib.rb
+++ b/test/zlib/test_zlib.rb
@@ -3,6 +3,7 @@
require 'test/unit'
require 'stringio'
require 'tempfile'
+require 'securerandom'
begin
require 'zlib'
@@ -443,6 +444,70 @@ if defined? Zlib
assert_raise(Zlib::StreamError) { z.set_dictionary("foo") }
z.close
end
+
+ def test_multithread_deflate
+ zd = Zlib::Deflate.new
+ s = "x" * 10000
+ (0...10).map do |x|
+ Thread.new do
+ 1000.times { zd.deflate(s) }
+ end
+ end.each do |th|
+ th.join
+ end
+ ensure
+ zd&.finish
+ zd&.close
+ end
+
+ def test_multithread_inflate
+ zi = Zlib::Inflate.new
+ s = Zlib.deflate("x" * 10000)
+ (0...10).map do |x|
+ Thread.new do
+ 1000.times { zi.inflate(s) }
+ end
+ end.each do |th|
+ th.join
+ end
+ ensure
+ zi&.finish
+ zi&.close
+ end
+
+ def test_recursive_deflate
+ original_gc_stress = GC.stress
+ GC.stress = true
+ zd = Zlib::Deflate.new
+
+ s = SecureRandom.random_bytes(1024**2)
+ assert_raise(Zlib::InProgressError) do
+ zd.deflate(s) do
+ zd.deflate(s)
+ end
+ end
+ ensure
+ GC.stress = original_gc_stress
+ zd&.finish
+ zd&.close
+ end
+
+ def test_recursive_inflate
+ original_gc_stress = GC.stress
+ GC.stress = true
+ zi = Zlib::Inflate.new
+
+ s = Zlib.deflate(SecureRandom.random_bytes(1024**2))
+
+ assert_raise(Zlib::InProgressError) do
+ zi.inflate(s) do
+ zi.inflate(s)
+ end
+ end
+ ensure
+ GC.stress = original_gc_stress
+ zi&.close
+ end
end
class TestZlibGzipFile < Test::Unit::TestCase
diff --git a/thread.c b/thread.c
index 90883b4cff..be6b46b155 100644
--- a/thread.c
+++ b/thread.c
@@ -741,6 +741,10 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start)
}
else {
errinfo = th->ec->errinfo;
+
+ VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef);
+ if (!NIL_P(exc)) errinfo = exc;
+
if (state == TAG_FATAL) {
/* fatal error within this thread, need to stop whole script */
}
diff --git a/tool/fake.rb b/tool/fake.rb
index 42174052e2..4946fd6234 100644
--- a/tool/fake.rb
+++ b/tool/fake.rb
@@ -43,6 +43,7 @@ prehook = proc do |extmk|
$extout_prefix = '$(extout)$(target_prefix)/'
config = RbConfig::CONFIG
mkconfig = RbConfig::MAKEFILE_CONFIG
+ $builtruby ||= File.join(builddir, config['RUBY_INSTALL_NAME'] + config['EXEEXT'])
RbConfig.fire_update!("builddir", builddir)
RbConfig.fire_update!("buildlibdir", builddir)
RbConfig.fire_update!("libdir", builddir)
diff --git a/tool/gem-unpack.rb b/tool/gem-unpack.rb
index 0ddcea0704..08faec9355 100644
--- a/tool/gem-unpack.rb
+++ b/tool/gem-unpack.rb
@@ -1,3 +1,4 @@
+require 'fileutils'
require 'rubygems'
require 'rubygems/package'
diff --git a/tool/lib/test/unit/core_assertions.rb b/tool/lib/test/unit/core_assertions.rb
index 00555d6e32..c25fc4e983 100644
--- a/tool/lib/test/unit/core_assertions.rb
+++ b/tool/lib/test/unit/core_assertions.rb
@@ -398,6 +398,39 @@ eom
end
alias all_assertions assert_all_assertions
+ # Expect +seq+ to respond to +first+ and +each+ methods, e.g.,
+ # Array, Range, Enumerator::ArithmeticSequence and other
+ # Enumerable-s, and each elements should be size factors.
+ #
+ # :yield: each elements of +seq+.
+ def assert_linear_performance(seq, rehearsal: nil, pre: ->(n) {n})
+ first = seq.first
+ *arg = pre.call(first)
+ times = (0..(rehearsal || (2 * first))).map do
+ st = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ yield(*arg)
+ t = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - st)
+ assert_operator 0, :<=, t
+ t.nonzero?
+ end
+ times.compact!
+ tmin, tmax = times.minmax
+ tmax *= tmax / tmin
+ tmax = 10**Math.log10(tmax).ceil
+
+ seq.each do |i|
+ next if i == first
+ t = tmax * i.fdiv(first)
+ *arg = pre.call(i)
+ message = "[#{i}]: in #{t}s"
+ Timeout.timeout(t, Timeout::Error, message) do
+ st = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ yield(*arg)
+ assert_operator (Process.clock_gettime(Process::CLOCK_MONOTONIC) - st), :<=, t, message
+ end
+ end
+ end
+
def message(msg = nil, *args, &default) # :nodoc:
if Proc === msg
super(nil, *args) do
diff --git a/version.h b/version.h
index dc3d527107..088503c681 100644
--- a/version.h
+++ b/version.h
@@ -1,12 +1,12 @@
# define RUBY_VERSION_MAJOR RUBY_API_VERSION_MAJOR
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
-#define RUBY_VERSION_TEENY 6
+#define RUBY_VERSION_TEENY 8
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 208
+#define RUBY_PATCHLEVEL 225
-#define RUBY_RELEASE_YEAR 2021
-#define RUBY_RELEASE_MONTH 12
-#define RUBY_RELEASE_DAY 31
+#define RUBY_RELEASE_YEAR 2023
+#define RUBY_RELEASE_MONTH 3
+#define RUBY_RELEASE_DAY 30
#include "ruby/version.h"
diff --git a/vm_method.c b/vm_method.c
index 3c087841dc..270334ea1b 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -584,6 +584,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil
if (RTEST(ruby_verbose) &&
type != VM_METHOD_TYPE_UNDEF &&
(old_def->alias_count == 0) &&
+ (!old_def->no_redef_warning) &&
!make_refined &&
old_def->type != VM_METHOD_TYPE_UNDEF &&
old_def->type != VM_METHOD_TYPE_ZSUPER &&
@@ -698,7 +699,13 @@ method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
rb_method_visibility_t visi, VALUE defined_class)
{
rb_method_entry_t *newme = rb_method_entry_make(klass, mid, defined_class, visi,
- me->def->type, method_definition_addref(me->def), 0, NULL);
+ me->def->type, me->def, 0, NULL);
+ if (newme == me) {
+ me->def->no_redef_warning = TRUE;
+ }
+ else {
+ method_definition_addref(me->def);
+ }
method_added(klass, mid);
return newme;
}