diff --git a/ext/openssl/History.md b/ext/openssl/History.md index ecc53fad3beb7c..32a2c0b2fb6ea7 100644 --- a/ext/openssl/History.md +++ b/ext/openssl/History.md @@ -1,3 +1,9 @@ +Version 3.3.2 +============= + +Merged changes in 3.1.3 and 3.2.3. + + Version 3.3.1 ============= @@ -80,6 +86,12 @@ And various non-user-visible changes and bug fixes. Please see the commit history for more details. +Version 3.2.3 +============= + +Merged changes in 3.1.3. + + Version 3.2.2 ============= @@ -132,6 +144,16 @@ Notable changes [[GitHub #141]](https://github.com/ruby/openssl/pull/141) +Version 3.1.3 +============= + +Bug fixes +--------- + +* Fix missing NULL check for `EVP_PKEY_get0()` functions with OpenSSL 3.x. + [[GitHub #957]](https://github.com/ruby/openssl/pull/957) + + Version 3.1.2 ============= diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c index ee2ff6786fbb28..9be5fe6f6320dc 100644 --- a/ext/openssl/ossl_config.c +++ b/ext/openssl/ossl_config.c @@ -426,7 +426,7 @@ Init_ossl_config(void) * configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for * the location of the file for your host. * - * See also http://www.openssl.org/docs/apps/config.html + * See also https://docs.openssl.org/master/man5/config/ */ cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject); diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 77082d5c348acb..561007fec8b058 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -21,6 +21,8 @@ EVP_PKEY *_pkey; \ GetPKeyDH((obj), _pkey); \ (dh) = EVP_PKEY_get0_DH(_pkey); \ + if ((dh) == NULL) \ + ossl_raise(eDHError, "failed to get DH from EVP_PKEY"); \ } while (0) /* diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index bf92e1ceac6412..cb38786b560c0a 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -21,6 +21,8 @@ EVP_PKEY *_pkey; \ GetPKeyDSA((obj), _pkey); \ (dsa) = EVP_PKEY_get0_DSA(_pkey); \ + if ((dsa) == NULL) \ + ossl_raise(eDSAError, "failed to get DSA from EVP_PKEY"); \ } while (0) static inline int diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index e3553c44188012..8c97297a56193e 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -22,6 +22,8 @@ static const rb_data_type_t ossl_ec_point_type; EVP_PKEY *_pkey; \ GetPKeyEC(obj, _pkey); \ (key) = EVP_PKEY_get0_EC_KEY(_pkey); \ + if ((key) == NULL) \ + ossl_raise(eECError, "failed to get EC_KEY from EVP_PKEY"); \ } while (0) #define GetECGroup(obj, group) do { \ diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 4f7862023a61c7..b2983d3b53cfc2 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -21,6 +21,8 @@ EVP_PKEY *_pkey; \ GetPKeyRSA((obj), _pkey); \ (rsa) = EVP_PKEY_get0_RSA(_pkey); \ + if ((rsa) == NULL) \ + ossl_raise(eRSAError, "failed to get RSA from EVP_PKEY"); \ } while (0) static inline int diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index 0dbf1fa3ec0918..3c842265af2630 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -572,9 +572,16 @@ strio_close(VALUE self) * call-seq: * close_read -> nil * - * Closes +self+ for reading; closed-write setting remains unchanged. + * Closes +self+ for reading; + * closed-write setting remains unchanged; + * returns +nil+: * - * Raises IOError if reading is attempted. + * strio = StringIO.new + * strio.closed_read? # => false + * strio.close_read # => nil + * strio.closed_read? # => true + * strio.closed_write? # => false + * strio.read # Raises IOError: not opened for reading * * Related: StringIO#close, StringIO#close_write. */ @@ -593,11 +600,16 @@ strio_close_read(VALUE self) * call-seq: * close_write -> nil * - * Closes +self+ for writing; closed-read setting remains unchanged. + * Closes +self+ for writing; closed-read setting remains unchanged; returns +nil+: * - * Raises IOError if writing is attempted. + * strio = StringIO.new + * strio.closed_write? # => false + * strio.close_write # => nil + * strio.closed_write? # => true + * strio.closed_read? # => false + * strio.write('foo') # Raises IOError: not opened for writing * - * Related: StringIO#close, StringIO#close_read. + * Related: StringIO#close, StringIO#close_read, StringIO#closed_write?. */ static VALUE strio_close_write(VALUE self) @@ -637,7 +649,14 @@ strio_closed(VALUE self) * call-seq: * closed_read? -> true or false * - * Returns +true+ if +self+ is closed for reading, +false+ otherwise. + * Returns whether +self+ is closed for reading: + * + * strio = StringIO.new + * strio.closed_read? # => false + * strio.close_read + * strio.closed_read? # => true + * + * Related: StringIO#closed?, StringIO#closed_write?, StringIO#close_read. */ static VALUE strio_closed_read(VALUE self) @@ -651,7 +670,14 @@ strio_closed_read(VALUE self) * call-seq: * closed_write? -> true or false * - * Returns +true+ if +self+ is closed for writing, +false+ otherwise. + * Returns whether +self+ is closed for writing: + * + * strio = StringIO.new + * strio.closed_write? # => false + * strio.close_write + * strio.closed_write? # => true + * + * Related: StringIO#close_write, StringIO#closed?, StringIO#closed_read?. */ static VALUE strio_closed_write(VALUE self) @@ -1436,15 +1462,177 @@ strio_readline(int argc, VALUE *argv, VALUE self) } /* + * :markup: markdown + * * call-seq: * each_line(sep = $/, chomp: false) {|line| ... } -> self * each_line(limit, chomp: false) {|line| ... } -> self * each_line(sep, limit, chomp: false) {|line| ... } -> self * - * Calls the block with each remaining line read from the stream; - * does nothing if already at end-of-file; - * returns +self+. - * See {Line IO}[rdoc-ref:IO@Line+IO]. + * With a block given calls the block with each remaining line (see "Position" below) in the stream; + * returns `self`. + * + * Leaves stream position as end-of-stream. + * + * **No Arguments** + * + * With no arguments given, + * reads lines using the default record separator global variable `$/`, whose initial value is `"\n"`. + * + * ``` + * strio = StringIO.new(TEXT) + * strio.each_line {|line| p line } + * strio.eof? # => true + * ``` + * + * Output: + * + * ``` + * "First line\n" + * "Second line\n" + * "\n" + * "Fourth line\n" + * "Fifth line\n" + * ``` + * + * **Argument `sep`** + * + * With only string argument `sep` given, + * reads lines using that string as the record separator: + * + * ``` + * strio = StringIO.new(TEXT) + * strio.each_line(' ') {|line| p line } + * ``` + * + * Output: + * + * ``` + * "First " + * "line\nSecond " + * "line\n\nFourth " + * "line\nFifth " + * "line\n" + * ``` + * + * **Argument `limit`** + * + * With only integer argument `limit` given, + * reads lines using the default record separator global variable `$/`, whose initial value is `"\n"`; + * also limits the size (in characters) of each line to the given limit: + * + * ``` + * strio = StringIO.new(TEXT) + * strio.each_line(10) {|line| p line } + * ``` + * + * Output: + * + * ``` + * "First line" + * "\n" + * "Second lin" + * "e\n" + * "\n" + * "Fourth lin" + * "e\n" + * "Fifth line" + * "\n" + * ``` + * **Arguments `sep` and `limit`** + * + * With arguments `sep` and `limit` both given, + * honors both: + * + * ``` + * strio = StringIO.new(TEXT) + * strio.each_line(' ', 10) {|line| p line } + * ``` + * + * Output: + * + * ``` + * "First " + * "line\nSecon" + * "d " + * "line\n\nFour" + * "th " + * "line\nFifth" + * " " + * "line\n" + * ``` + * + * **Position** + * + * As stated above, method `each` _remaining_ line in the stream. + * + * In the examples above each `strio` object starts with its position at beginning-of-stream; + * but in other cases the position may be anywhere (see StringIO#pos): + * + * ``` + * strio = StringIO.new(TEXT) + * strio.pos = 30 # Set stream position to character 30. + * strio.each_line {|line| p line } + * ``` + * + * Output: + * + * ``` + * " line\n" + * "Fifth line\n" + * ``` + * + * **Special Record Separators** + * + * Like some methds in class `IO`, StringIO.each honors two special record separators; + * see {Special Line Separators}[rdoc-ref:IO@Special+Line+Separator+Values]. + * + * ``` + * strio = StringIO.new(TEXT) + * strio.each_line('') {|line| p line } # Read as paragraphs (separated by blank lines). + * ``` + * + * Output: + * + * ``` + * "First line\nSecond line\n\n" + * "Fourth line\nFifth line\n" + * ``` + * + * ``` + * strio = StringIO.new(TEXT) + * strio.each_line(nil) {|line| p line } # "Slurp"; read it all. + * ``` + * + * Output: + * + * ``` + * "First line\nSecond line\n\nFourth line\nFifth line\n" + * ``` + * + * **Keyword Argument `chomp`** + * + * With keyword argument `chomp` given as `true` (the default is `false`), + * removes trailing newline (if any) from each line: + * + * ``` + * strio = StringIO.new(TEXT) + * strio.each_line(chomp: true) {|line| p line } + * ``` + * + * Output: + * + * ``` + * "First line" + * "Second line" + * "" + * "Fourth line" + * "Fifth line" + * ``` + * + * With no block given, returns a new {Enumerator}[rdoc-ref:Enumerator]. + * + * Related: StringIO.each_byte, StringIO.each_char, StringIO.each_codepoint. */ static VALUE strio_each(int argc, VALUE *argv, VALUE self) @@ -1943,15 +2131,34 @@ strio_set_encoding_by_bom(VALUE self) } /* + * :markup: markdown + * * \IO streams for strings, with access similar to * {IO}[rdoc-ref:IO]; * see {IO}[rdoc-ref:IO]. * - * === About the Examples + * ### About the Examples * * Examples on this page assume that \StringIO has been required: * - * require 'stringio' + * ``` + * require 'stringio' + * ``` + * + * And that these constants have been defined: + * + * ``` + * TEXT = <