diff --git a/NEWS.md b/NEWS.md index 68801e40381aa3..71f1b3f929ce2c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -75,15 +75,15 @@ releases. ### The following default gems are updated. * RubyGems 4.1.0.dev - * 4.0.3 to [v4.0.4][RubyGems-v4.0.4], [v4.0.5][RubyGems-v4.0.5], [v4.0.6][RubyGems-v4.0.6], [v4.0.7][RubyGems-v4.0.7], [v4.0.8][RubyGems-v4.0.8], [v4.0.9][RubyGems-v4.0.9], [v4.0.10][RubyGems-v4.0.10], [v4.0.11][RubyGems-v4.0.11], [v4.0.12][RubyGems-v4.0.12], [v4.0.13][RubyGems-v4.0.13], [v4.0.14][RubyGems-v4.0.14] + * 4.0.3 to [v4.0.4][RubyGems-v4.0.4], [v4.0.5][RubyGems-v4.0.5], [v4.0.6][RubyGems-v4.0.6], [v4.0.7][RubyGems-v4.0.7], [v4.0.8][RubyGems-v4.0.8], [v4.0.9][RubyGems-v4.0.9], [v4.0.10][RubyGems-v4.0.10], [v4.0.11][RubyGems-v4.0.11], [v4.0.12][RubyGems-v4.0.12], [v4.0.13][RubyGems-v4.0.13], [v4.0.14][RubyGems-v4.0.14], [v4.0.15][RubyGems-v4.0.15] * bundler 4.1.0.dev - * 4.0.3 to [v4.0.4][bundler-v4.0.4], [v4.0.5][bundler-v4.0.5], [v4.0.6][bundler-v4.0.6], [v4.0.7][bundler-v4.0.7], [v4.0.8][bundler-v4.0.8], [v4.0.9][bundler-v4.0.9], [v4.0.10][bundler-v4.0.10], [v4.0.11][bundler-v4.0.11], [v4.0.12][bundler-v4.0.12], [v4.0.13][bundler-v4.0.13], [v4.0.14][bundler-v4.0.14] + * 4.0.3 to [v4.0.4][bundler-v4.0.4], [v4.0.5][bundler-v4.0.5], [v4.0.6][bundler-v4.0.6], [v4.0.7][bundler-v4.0.7], [v4.0.8][bundler-v4.0.8], [v4.0.9][bundler-v4.0.9], [v4.0.10][bundler-v4.0.10], [v4.0.11][bundler-v4.0.11], [v4.0.12][bundler-v4.0.12], [v4.0.13][bundler-v4.0.13], [v4.0.14][bundler-v4.0.14], [v4.0.15][bundler-v4.0.15] * erb 6.0.4 * 6.0.1 to [v6.0.1.1][erb-v6.0.1.1], [v6.0.2][erb-v6.0.2], [v6.0.3][erb-v6.0.3], [v6.0.4][erb-v6.0.4] * ipaddr 1.2.9 * 1.2.8 to [v1.2.9][ipaddr-v1.2.9] * json 2.20.0 - * 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2], [v2.19.3][json-v2.19.3], [v2.19.4][json-v2.19.4], [v2.19.5][json-v2.19.5], [v2.19.6][json-v2.19.6], [v2.19.7][json-v2.19.7], [v2.19.8][json-v2.19.8], [v2.19.9][json-v2.19.9] + * 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2], [v2.19.3][json-v2.19.3], [v2.19.4][json-v2.19.4], [v2.19.5][json-v2.19.5], [v2.19.6][json-v2.19.6], [v2.19.7][json-v2.19.7], [v2.19.8][json-v2.19.8], [v2.19.9][json-v2.19.9], [v2.20.0][json-v2.20.0] * openssl 4.0.2 * 4.0.0 to [v4.0.1][openssl-v4.0.1], [v4.0.2][openssl-v4.0.2] * pp 0.6.4 @@ -213,6 +213,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [RubyGems-v4.0.12]: https://github.com/rubygems/rubygems/releases/tag/v4.0.12 [RubyGems-v4.0.13]: https://github.com/rubygems/rubygems/releases/tag/v4.0.13 [RubyGems-v4.0.14]: https://github.com/rubygems/rubygems/releases/tag/v4.0.14 +[RubyGems-v4.0.15]: https://github.com/rubygems/rubygems/releases/tag/v4.0.15 [bundler-v4.0.4]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.4 [bundler-v4.0.5]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.5 [bundler-v4.0.6]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.6 @@ -224,6 +225,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [bundler-v4.0.12]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.12 [bundler-v4.0.13]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.13 [bundler-v4.0.14]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.14 +[bundler-v4.0.15]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.15 [erb-v6.0.1.1]: https://github.com/ruby/erb/releases/tag/v6.0.1.1 [erb-v6.0.2]: https://github.com/ruby/erb/releases/tag/v6.0.2 [erb-v6.0.3]: https://github.com/ruby/erb/releases/tag/v6.0.3 @@ -240,6 +242,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [json-v2.19.7]: https://github.com/ruby/json/releases/tag/v2.19.7 [json-v2.19.8]: https://github.com/ruby/json/releases/tag/v2.19.8 [json-v2.19.9]: https://github.com/ruby/json/releases/tag/v2.19.9 +[json-v2.20.0]: https://github.com/ruby/json/releases/tag/v2.20.0 [openssl-v4.0.1]: https://github.com/ruby/openssl/releases/tag/v4.0.1 [openssl-v4.0.2]: https://github.com/ruby/openssl/releases/tag/v4.0.2 [pp-v0.6.4]: https://github.com/ruby/pp/releases/tag/v0.6.4 diff --git a/compile.c b/compile.c index 4a0a5e83f3a3c0..c71a2e79cbb967 100644 --- a/compile.c +++ b/compile.c @@ -3381,6 +3381,22 @@ ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc) #define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) +static VALUE +iseq_reg_compile(rb_iseq_t *iseq, VALUE str, int options, const char *sourcefile, int sourceline) +{ + VALUE errinfo = rb_errinfo(); + VALUE re = rb_reg_compile(str, options, sourcefile, sourceline); + if (NIL_P(re)) { + VALUE message = rb_attr_get(rb_errinfo(), idMesg); + rb_set_errinfo(errinfo); + COMPILE_ERROR(iseq, sourceline, "%" PRIsVALUE, message); + } + else { + RB_OBJ_SET_SHAREABLE(re); + } + return re; +} + static int iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt) { @@ -3952,16 +3968,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal int opt = (int)FIX2LONG(OPERAND_AT(next, 0)); VALUE path = rb_iseq_path(iseq); int line = iobj->insn_info.line_no; - VALUE errinfo = rb_errinfo(); - VALUE re = rb_reg_compile(src, opt, RSTRING_PTR(path), line); - if (NIL_P(re)) { - VALUE message = rb_attr_get(rb_errinfo(), idMesg); - rb_set_errinfo(errinfo); - COMPILE_ERROR(iseq, line, "%" PRIsVALUE, message); - } - else { - RB_OBJ_SET_SHAREABLE(re); - } + VALUE re = iseq_reg_compile(iseq, src, opt, RSTRING_PTR(path), line); /* The folded operand is a Regexp, so the instruction must be * putobject: dupstring/dupchilledstring would resurrect the * Regexp as a String at run time (e.g. for a /o regexp whose @@ -4799,8 +4806,7 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i if (!RNODE_DREGX(node)->nd_next) { if (!popped) { VALUE src = rb_node_dregx_string_val(node); - VALUE match = rb_reg_compile(src, cflag, NULL, 0); - RB_OBJ_SET_SHAREABLE(match); + VALUE match = iseq_reg_compile(iseq, src, cflag, NULL, 0); ADD_INSN1(ret, node, putobject, match); RB_OBJ_WRITTEN(iseq, Qundef, match); } diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index a52a91fdecf15e..0a9eab4f80b6d9 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -59,12 +59,6 @@ (LIBRESSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12))) #endif -#if OSSL_OPENSSL_PREREQ(3, 0, 0) -# define OSSL_3_const const -#else -# define OSSL_3_const /* const */ -#endif - #if !defined(OPENSSL_NO_ENGINE) && !OSSL_OPENSSL_PREREQ(3, 0, 0) # define OSSL_USE_ENGINE #endif diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 558bc56bfbd54b..f33121d0fab933 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -141,8 +141,7 @@ static VALUE ossl_dh_initialize_copy(VALUE self, VALUE other) { EVP_PKEY *pkey; - DH *dh; - OSSL_3_const DH *dh_other; + DH *dh, *dh_other; const BIGNUM *pub, *priv; TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); @@ -188,7 +187,7 @@ ossl_dh_initialize_copy(VALUE self, VALUE other) static VALUE ossl_dh_is_public(VALUE self) { - OSSL_3_const DH *dh; + const DH *dh; const BIGNUM *bn; GetDH(self, dh); @@ -207,7 +206,7 @@ ossl_dh_is_public(VALUE self) static VALUE ossl_dh_is_private(VALUE self) { - OSSL_3_const DH *dh; + const DH *dh; const BIGNUM *bn; GetDH(self, dh); @@ -244,7 +243,7 @@ ossl_dh_is_private(VALUE self) static VALUE ossl_dh_export(VALUE self) { - OSSL_3_const DH *dh; + const DH *dh; BIO *out; VALUE str; @@ -277,7 +276,7 @@ ossl_dh_export(VALUE self) static VALUE ossl_dh_to_der(VALUE self) { - OSSL_3_const DH *dh; + const DH *dh; unsigned char *p; long len; VALUE str; @@ -319,7 +318,7 @@ ossl_dh_check_params(VALUE self) ret = EVP_PKEY_param_check(pctx); EVP_PKEY_CTX_free(pctx); #else - OSSL_3_const DH *dh; + const DH *dh; int codes; GetDH(self, dh); diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 0ef1c43f4c9efe..112ea74660fe48 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -26,7 +26,7 @@ } while (0) static inline int -DSA_HAS_PRIVATE(OSSL_3_const DSA *dsa) +DSA_HAS_PRIVATE(const DSA *dsa) { const BIGNUM *bn; DSA_get0_key(dsa, NULL, &bn); @@ -34,7 +34,7 @@ DSA_HAS_PRIVATE(OSSL_3_const DSA *dsa) } static inline int -DSA_PRIVATE(VALUE obj, OSSL_3_const DSA *dsa) +DSA_PRIVATE(VALUE obj, const DSA *dsa) { return DSA_HAS_PRIVATE(dsa) || OSSL_PKEY_IS_PRIVATE(obj); } @@ -152,7 +152,7 @@ static VALUE ossl_dsa_initialize_copy(VALUE self, VALUE other) { EVP_PKEY *pkey; - OSSL_3_const DSA *dsa; + const DSA *dsa; DSA *dsa_new; TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); @@ -207,7 +207,7 @@ ossl_dsa_is_public(VALUE self) static VALUE ossl_dsa_is_private(VALUE self) { - OSSL_3_const DSA *dsa; + const DSA *dsa; GetDSA(self, dsa); @@ -276,7 +276,7 @@ ossl_dsa_is_private(VALUE self) static VALUE ossl_dsa_export(int argc, VALUE *argv, VALUE self) { - OSSL_3_const DSA *dsa; + const DSA *dsa; GetDSA(self, dsa); if (DSA_HAS_PRIVATE(dsa)) @@ -302,7 +302,7 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) static VALUE ossl_dsa_to_der(VALUE self) { - OSSL_3_const DSA *dsa; + const DSA *dsa; GetDSA(self, dsa); if (DSA_HAS_PRIVATE(dsa)) diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index bd964767774805..985814e43644f8 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -199,7 +199,7 @@ static VALUE ossl_ec_key_initialize_copy(VALUE self, VALUE other) { EVP_PKEY *pkey; - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; EC_KEY *ec_new; TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); @@ -232,7 +232,7 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other) static VALUE ossl_ec_key_get_group(VALUE self) { - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; const EC_GROUP *group; GetEC(self, ec); @@ -277,7 +277,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v) */ static VALUE ossl_ec_key_get_private_key(VALUE self) { - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; const BIGNUM *bn; GetEC(self, ec); @@ -328,7 +328,7 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key) */ static VALUE ossl_ec_key_get_public_key(VALUE self) { - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; const EC_POINT *point; GetEC(self, ec); @@ -380,7 +380,7 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) */ static VALUE ossl_ec_key_is_public(VALUE self) { - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; GetEC(self, ec); @@ -396,7 +396,7 @@ static VALUE ossl_ec_key_is_public(VALUE self) */ static VALUE ossl_ec_key_is_private(VALUE self) { - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; GetEC(self, ec); @@ -464,7 +464,7 @@ static VALUE ossl_ec_key_is_private(VALUE self) static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self) { - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; GetEC(self, ec); if (EC_KEY_get0_public_key(ec) == NULL) @@ -492,7 +492,7 @@ ossl_ec_key_export(int argc, VALUE *argv, VALUE self) static VALUE ossl_ec_key_to_der(VALUE self) { - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; GetEC(self, ec); if (EC_KEY_get0_public_key(ec) == NULL) @@ -567,7 +567,7 @@ static VALUE ossl_ec_key_check_key(VALUE self) EVP_PKEY_CTX_free(pctx); #else - OSSL_3_const EC_KEY *ec; + const EC_KEY *ec; GetEC(self, ec); if (EC_KEY_check_key(ec) != 1) diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 7af0e220991c99..7ddc3322a37b4e 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -26,7 +26,7 @@ } while (0) static inline int -RSA_HAS_PRIVATE(OSSL_3_const RSA *rsa) +RSA_HAS_PRIVATE(const RSA *rsa) { const BIGNUM *e, *d; @@ -35,7 +35,7 @@ RSA_HAS_PRIVATE(OSSL_3_const RSA *rsa) } static inline int -RSA_PRIVATE(VALUE obj, OSSL_3_const RSA *rsa) +RSA_PRIVATE(VALUE obj, const RSA *rsa) { return RSA_HAS_PRIVATE(rsa) || OSSL_PKEY_IS_PRIVATE(obj); } @@ -148,7 +148,7 @@ static VALUE ossl_rsa_initialize_copy(VALUE self, VALUE other) { EVP_PKEY *pkey; - OSSL_3_const RSA *rsa; + const RSA *rsa; RSA *rsa_new; TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); @@ -183,7 +183,7 @@ ossl_rsa_initialize_copy(VALUE self, VALUE other) static VALUE ossl_rsa_is_public(VALUE self) { - OSSL_3_const RSA *rsa; + const RSA *rsa; GetRSA(self, rsa); /* @@ -202,7 +202,7 @@ ossl_rsa_is_public(VALUE self) static VALUE ossl_rsa_is_private(VALUE self) { - OSSL_3_const RSA *rsa; + const RSA *rsa; GetRSA(self, rsa); @@ -212,7 +212,7 @@ ossl_rsa_is_private(VALUE self) static int can_export_rsaprivatekey(VALUE self) { - OSSL_3_const RSA *rsa; + const RSA *rsa; const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; GetRSA(self, rsa); diff --git a/test/net/http/utils.rb b/test/net/http/utils.rb index 0b9e440e7cbcbb..f499963d418729 100644 --- a/test/net/http/utils.rb +++ b/test/net/http/utils.rb @@ -26,14 +26,14 @@ def initialize(config, &block) def start @thread = Thread.new do loop do - socket = (@ssl_server || @server).accept + socket = server.accept run(socket) rescue ensure socket&.close end ensure - (@ssl_server || @server).close + server.close end end @@ -44,6 +44,7 @@ def run(socket) def shutdown @thread&.kill @thread&.join + server&.close end def mount(path, proc) @@ -94,6 +95,10 @@ def port @port end + private def server + @ssl_server || @server + end + class Request attr_reader :method, :path, :headers, :query, :body def initialize(method, path, headers, socket) diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index c9b5f56f731ee5..544d9e0b357ba0 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -307,6 +307,52 @@ def test_ml_kem assert_equal(shared_secret, privkey.decapsulate(ciphertext)) end + def test_dhkem_x25519 + # DHKEM (RFC 9180) and the X25519/X448 curves are not FIPS-approved; the + # KEM is built into the default provider only, not the FIPS module. + omit_on_fips + # EVP_KEM-X25519 / EVP_KEM-X448 were added in OpenSSL 3.2, but the DHKEM + # operation defaults correctly (without an explicit OSSL_KEM_PARAM_OPERATION) + # only since OpenSSL 3.5. + omit "DHKEM is not supported" unless openssl?(3, 5, 0) + + pkey = OpenSSL::PKey.generate_key("X25519") + raw_public_key = pkey.raw_public_key + raw_private_key = pkey.raw_private_key + + assert_match(/type_name=X25519/, pkey.inspect) + assert_equal(32, raw_public_key.bytesize) # Npk + assert_equal(32, raw_private_key.bytesize) # Nsk + + pubkey = OpenSSL::PKey.new_raw_public_key("X25519", raw_public_key) + ciphertext, shared_secret = pubkey.encapsulate + assert_equal(32, ciphertext.bytesize) # Nenc + assert_equal(32, shared_secret.bytesize) # Nsecret + assert_equal(shared_secret, pkey.decapsulate(ciphertext)) + + privkey = OpenSSL::PKey.new_raw_private_key("X25519", raw_private_key) + assert_equal(shared_secret, privkey.decapsulate(ciphertext)) + end + + def test_dhkem_ec + # DHKEM (RFC 9180) is built into the default provider only, not the FIPS + # module. + omit_on_fips + # EVP_KEM-EC (RFC 9180 DHKEM over NIST curves) was added in OpenSSL 3.2, but + # the DHKEM operation defaults correctly (without an explicit + # OSSL_KEM_PARAM_OPERATION) only since OpenSSL 3.5. + omit "DHKEM is not supported" unless openssl?(3, 5, 0) + + pkey = OpenSSL::PKey::EC.generate("prime256v1") + assert_match(/type_name=EC/, pkey.inspect) + + pubkey = OpenSSL::PKey.read(pkey.public_to_der) + ciphertext, shared_secret = pubkey.encapsulate + assert_equal(65, ciphertext.bytesize) # Nenc + assert_equal(32, shared_secret.bytesize) # Nsecret + assert_equal(shared_secret, pkey.decapsulate(ciphertext)) + end + def test_raw_initialize_errors assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("foo123", "xxx") } assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("ED25519", "xxx") } diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 62adae415914a4..f1a7b9a311a328 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1405,6 +1405,10 @@ def test_unterminated_regexp_error assert_not_match(/unexpected tSTRING_END/, e.message) end + def test_invalid_character_regexp_error + assert_syntax_error('/#{"\xcd"}/', /invalid multibyte character/) + end + def test_lparenarg o = Struct.new(:x).new def o.i(x) diff --git a/tool/lib/leakchecker.rb b/tool/lib/leakchecker.rb index 33a546699f6145..7bd479bbd3f83d 100644 --- a/tool/lib/leakchecker.rb +++ b/tool/lib/leakchecker.rb @@ -125,7 +125,7 @@ def check_fd_leak(test_name) fd_index, node_index = columns.index('FD'), columns.index('NODE') open_list.reject! do |of| of = of.chomp.split(' ', node_index + 2) - if of[node_index] == 'TCP' and of.last.end_with?('(CLOSE_WAIT)') + if of[node_index] == 'TCP' and of.last.end_with?('(CLOSE_WAIT)', '(CLOSED)') fd = of[fd_index].to_i inspect.delete(fd) h.delete(fd)