summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Sherwood <paul.sherwood@codethink.co.uk>2014-04-20 09:01:04 +0000
committerPaul Sherwood <paul.sherwood@codethink.co.uk>2014-04-20 09:01:04 +0000
commit6ecf40e1fa1b2c55f63d0ccb46bce2fca73b40ad (patch)
tree368a0326bcf36bc7e06cbbe7a1d55b752afd86ba
parentcb3ea602294b5038b5f7ac21d3875a2b52342956 (diff)
parent680d09b61ea7d850e27944311723a40c596e5d95 (diff)
downloadruby-baserock/ps/proto-web-system.tar.gz
Merge commit '680d09' into baserock/ps/proto-web-systembaserock/ps/proto-web-system
-rw-r--r--ChangeLog894
-rw-r--r--Makefile.in2
-rw-r--r--array.c15
-rw-r--r--benchmark/driver.rb2
-rw-r--r--bignum.c2
-rw-r--r--class.c3
-rw-r--r--common.mk3
-rw-r--r--compar.c9
-rw-r--r--configure.in79
-rw-r--r--enc/depend2
-rw-r--r--enumerator.c17
-rw-r--r--eval.c4
-rw-r--r--eval_jump.c12
-rw-r--r--ext/bigdecimal/bigdecimal.c15
-rw-r--r--ext/date/date_core.c138
-rw-r--r--ext/date/date_parse.c8
-rw-r--r--ext/date/date_strptime.c4
-rw-r--r--ext/dl/cptr.c15
-rw-r--r--ext/dl/lib/dl/func.rb3
-rw-r--r--ext/fiddle/closure.c7
-rw-r--r--ext/fiddle/function.c9
-rw-r--r--ext/io/console/console.c2
-rw-r--r--ext/json/generator/depend1
-rw-r--r--ext/json/generator/generator.c14
-rw-r--r--ext/json/parser/depend1
-rw-r--r--ext/openssl/lib/openssl/ssl-internal.rb18
-rw-r--r--ext/openssl/ossl.c19
-rw-r--r--ext/openssl/ossl.h8
-rw-r--r--ext/openssl/ossl_asn1.c17
-rw-r--r--ext/openssl/ossl_cipher.c8
-rw-r--r--ext/openssl/ossl_engine.c17
-rw-r--r--ext/openssl/ossl_pkey_dh.c3
-rw-r--r--ext/openssl/ossl_pkey_ec.c4
-rw-r--r--ext/openssl/ossl_ssl.c14
-rw-r--r--ext/openssl/ossl_x509cert.c43
-rw-r--r--ext/openssl/ruby_missing.h9
-rw-r--r--ext/pty/pty.c6
-rw-r--r--ext/ripper/lib/ripper/lexer.rb10
-rw-r--r--ext/socket/ancdata.c18
-rw-r--r--ext/socket/extconf.rb6
-rw-r--r--ext/socket/init.c8
-rw-r--r--ext/socket/lib/socket.rb79
-rw-r--r--ext/socket/raddrinfo.c12
-rw-r--r--ext/strscan/strscan.c56
-rw-r--r--ext/syslog/syslog.c34
-rw-r--r--ext/tk/extconf.rb68
-rw-r--r--ext/tk/lib/tk/canvas.rb9
-rw-r--r--ext/tk/lib/tk/msgcat.rb41
-rw-r--r--ext/tk/lib/tk/namespace.rb7
-rw-r--r--ext/tk/lib/tkextlib/tktable/tktable.rb2
-rw-r--r--ext/tk/sample/demos-en/tree.rb2
-rw-r--r--ext/tk/sample/demos-en/widget6
-rw-r--r--ext/tk/sample/demos-jp/tree.rb2
-rw-r--r--ext/tk/sample/demos-jp/widget6
-rw-r--r--ext/tk/sample/scrollframe.rb2
-rw-r--r--ext/tk/stubs.c14
-rw-r--r--ext/tk/tcltklib.c15
-rw-r--r--ext/win32ole/win32ole.c11
-rw-r--r--ext/zlib/zlib.c8
-rw-r--r--file.c42
-rw-r--r--gc.c19
-rw-r--r--hash.c38
-rw-r--r--id.c1
-rw-r--r--include/ruby/intern.h16
-rw-r--r--include/ruby/ruby.h1
-rw-r--r--include/ruby/st.h1
-rw-r--r--include/ruby/win32.h14
-rw-r--r--internal.h3
-rw-r--r--io.c75
-rw-r--r--iseq.c8
-rw-r--r--lib/cgi/core.rb11
-rw-r--r--lib/drb/ssl.rb5
-rw-r--r--lib/gserver.rb2
-rw-r--r--lib/mkmf.rb59
-rw-r--r--lib/net/http.rb11
-rw-r--r--lib/net/imap.rb7
-rw-r--r--lib/net/pop.rb4
-rw-r--r--lib/net/smtp.rb13
-rw-r--r--lib/open-uri.rb7
-rw-r--r--lib/optparse.rb43
-rw-r--r--lib/resolv.rb27
-rw-r--r--lib/rexml/document.rb2
-rw-r--r--lib/rubygems.rb2
-rw-r--r--lib/rubygems/version.rb4
-rw-r--r--lib/tempfile.rb2
-rw-r--r--lib/thread.rb16
-rw-r--r--lib/time.rb6
-rw-r--r--lib/webrick/htmlutils.rb5
-rw-r--r--lib/webrick/httputils.rb14
-rw-r--r--lib/yaml.rb52
-rw-r--r--node.h1
-rw-r--r--numeric.c12
-rw-r--r--object.c5
-rw-r--r--parse.y126
-rw-r--r--proc.c51
-rw-r--r--process.c40
-rw-r--r--rational.c4
-rw-r--r--regexec.c7
-rw-r--r--ruby_atomic.h62
-rw-r--r--signal.c14
-rw-r--r--st.c39
-rw-r--r--string.c12
-rw-r--r--template/id.h.tmpl2
-rw-r--r--test/bigdecimal/test_bigdecimal.rb34
-rw-r--r--test/coverage/test_coverage.rb2
-rw-r--r--test/date/test_date_parse.rb6
-rw-r--r--test/date/test_switch_hitter.rb55
-rw-r--r--test/dl/test_base.rb3
-rw-r--r--test/fiddle/helper.rb3
-rw-r--r--test/mkmf/test_framework.rb46
-rw-r--r--test/net/imap/Makefile15
-rw-r--r--test/net/imap/cacert.pem84
-rw-r--r--test/net/imap/server.crt65
-rw-r--r--test/net/imap/test_imap_response_parser.rb25
-rw-r--r--test/net/smtp/test_smtp.rb13
-rw-r--r--test/openssl/test_asn1.rb8
-rw-r--r--test/openssl/test_pkey_ec.rb32
-rw-r--r--test/openssl/test_ssl.rb56
-rw-r--r--test/optparse/test_acceptable.rb195
-rw-r--r--test/resolv/test_addr.rb13
-rw-r--r--test/resolv/test_dns.rb11
-rw-r--r--test/ripper/test_parser_events.rb22
-rw-r--r--test/ripper/test_scanner_events.rb48
-rw-r--r--test/ruby/envutil.rb25
-rw-r--r--test/ruby/memory_status.rb2
-rw-r--r--test/ruby/test_array.rb27
-rw-r--r--test/ruby/test_beginendblock.rb11
-rw-r--r--test/ruby/test_comparable.rb7
-rw-r--r--test/ruby/test_enumerator.rb31
-rw-r--r--test/ruby/test_float.rb12
-rw-r--r--test/ruby/test_gc.rb14
-rw-r--r--test/ruby/test_hash.rb37
-rw-r--r--test/ruby/test_io.rb97
-rw-r--r--test/ruby/test_io_m17n.rb12
-rw-r--r--test/ruby/test_m17n.rb2
-rw-r--r--test/ruby/test_method.rb14
-rw-r--r--test/ruby/test_module.rb44
-rw-r--r--test/ruby/test_pack.rb1
-rw-r--r--test/ruby/test_parse.rb21
-rw-r--r--test/ruby/test_proc.rb50
-rw-r--r--test/ruby/test_process.rb12
-rw-r--r--test/ruby/test_sprintf_comb.rb46
-rw-r--r--test/ruby/test_symbol.rb29
-rw-r--r--test/ruby/test_syntax.rb5
-rw-r--r--test/ruby/test_thread.rb27
-rw-r--r--test/ruby/test_time.rb23
-rw-r--r--test/rubygems/test_gem_requirement.rb20
-rw-r--r--test/rubygems/test_gem_version.rb12
-rw-r--r--test/socket/test_socket.rb71
-rw-r--r--test/socket/test_unix.rb23
-rw-r--r--test/test_mathn.rb98
-rw-r--r--test/test_tempfile.rb15
-rw-r--r--test/test_time.rb2
-rw-r--r--test/thread/test_queue.rb22
-rw-r--r--test/webrick/test_cgi.rb2
-rw-r--r--test/webrick/test_httputils.rb4
-rw-r--r--thread.c44
-rw-r--r--thread_pthread.c17
-rw-r--r--time.c42
-rwxr-xr-xtool/mkconfig.rb1
-rw-r--r--util.c18
-rw-r--r--version.h10
-rw-r--r--vm.c8
-rw-r--r--vm_eval.c17
-rw-r--r--vsnprintf.c34
-rw-r--r--win32/Makefile.sub17
-rw-r--r--win32/win32.c127
167 files changed, 3780 insertions, 837 deletions
diff --git a/ChangeLog b/ChangeLog
index 6711d7a615..17715d02b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,897 @@
+Mon Mar 31 15:38:07 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/openssl/ossl.c (ossl_make_error): check NULL for unknown
+ error reasons with old OpenSSL, and insert a colon iff formatted
+ message is not empty.
+
+Mon Feb 24 12:42:01 2014 Zachary Scott <e@zzak.io>
+
+ * lib/open-uri.rb: [DOC] use lower case version of core classes, same
+ as commit r44878, based on patch by Jonathan Jackson [Bug #9483]
+
+Mon Feb 24 12:42:01 2014 Zachary Scott <e@zzak.io>
+
+ * ext/ripper/lib/ripper/lexer.rb: [DOC] use lower case version of core
+ classes when referring to return value, since we aren't directly
+ talking about the class. Patch by Jonathan Jackson [Bug #9483]
+
+Mon Feb 24 12:39:11 2014 Zachary Scott <e@zzak.io>
+
+ * ext/openssl/ossl_pkey_dh.c: Fixed typo by Sandor Szuecs [Bug #9243]
+
+Mon Feb 24 12:33:38 2014 Zachary Scott <e@zzak.io>
+
+ * lib/net/smtp.rb: [DOC] Remove dead link to RAA by Giorgos Tsiftsis
+ Fixes the following bugs: [Bug #9152] [Bug #9268] [Bug #9394]
+ * lib/open-uri.rb: ditto
+
+Sat Feb 22 19:14:25 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/io/console/console.c (console_dev): need read access for conout$
+ because some functions need it. [Bug#9554]
+
+Sat Feb 22 10:09:42 2014 Eric Wong <e@80x24.org>
+
+ * ext/socket/ancdata.c (bsock_sendmsg_internal): only retry on error
+ (bsock_recvmsg_internal): ditto
+ * test/socket/test_unix.rb: test above for infinite loop
+
+Sat Feb 22 09:51:53 2014 Shugo Maeda <shugo@ruby-lang.org>
+
+ * ext/socket/init.c (wait_connectable): break if the socket is
+ writable to avoid infinite loops on FreeBSD and other platforms
+ which conforms to SUSv3. This problem cannot be reproduced with
+ loopback interfaces, so it's hard to write test code.
+ rsock_connect() and wait_connectable() are overly complicated, so
+ they should be refactored, but I commit this fix as a workaround
+ for the release of Ruby 1.9.3 scheduled on Feb 24.
+ [ruby-core:60940] [Bug #9547]
+
+Sat Feb 22 09:26:05 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * class.c (rb_mod_init_copy): do nothing if copying self.
+ [ruby-dev:47989] [Bug #9535]
+
+Tue Feb 18 22:53:34 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ruby_atomic.h: fixed merge mistake of r44946. reported by ngoto at
+ [ruby-dev:47980] [Backport #9530]
+
+Mon Feb 17 18:04:40 2014 Aaron Pfeifer <aaron.pfeifer@gmail.com>
+
+ * thread.c (terminate_atfork_i): fix locking mutexes not unlocked in
+ forks when not tracked in thread. [ruby-core:55102] [Bug #8433]
+
+Fri Feb 14 21:01:12 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/socket: revert r44943 because it causes errors on some linux
+ platforms.
+
+Fri Feb 14 20:52:31 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * configure.in (ARCH_FLAG): __sync_val_compare_and_swap_4 needs
+ -march=i486 on at least linux gcc 4.1.
+
+Fri Feb 14 19:07:13 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby_atomic.h (ATOMIC_PTR_EXCHANGE): atomic exchange function for
+ a generic pointer.
+
+Fri Feb 14 19:07:13 2014 Masaki Matsushita <glass.saga@gmail.com>
+
+ * ruby_atomic.h: define ATOMIC_SIZE_CAS() with
+ __atomic_compare_exchange_n() and refactoring.
+
+Fri Feb 14 19:07:13 2014 Masaki Matsushita <glass.saga@gmail.com>
+
+ * ruby_atomic.h: use __atomic builtin functions supported by GCC.
+ __sync family are legacy functions now and it is recommended
+ that new code use the __atomic functions.
+ http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
+
+ * configure.in: check existence of __atomic functions.
+
+Fri Feb 14 16:21:28 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ruby_atomic.h (ATOMIC_CAS): added.
+
+ * signal.c (ruby_atomic_compare_and_swap): ATOMIC_CAS implementation
+ for non-VC/gcc platform.
+
+Fri Feb 14 15:56:27 2014 Tanaka Akira <akr@fsij.org>
+
+ * lib/resolv.rb: Ignore name servers which cause EAFNOSUPPORT on
+ socket creation.
+ Reported by Bjoern Rennhak. [ruby-core:60442] [Bug #9477]
+
+Fri Feb 14 15:54:57 2014 Tanaka Akira <akr@fsij.org>
+
+ * lib/resolv.rb (Resolv::DNS::Message::MessageDecoder): Raise
+ DecodeError if no data before the limit.
+ Reported by Will Bryant. [ruby-core:60557] [Bug #9498]
+
+Fri Feb 14 15:49:55 2014 Eric Wong <e@80x24.org>
+
+ * ext/json/generator/depend: add build dependencies for json extension
+ [Bug #9374] [ruby-core:59609]
+ * ext/json/parser/depend: ditto
+
+Fri Feb 14 15:40:32 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * iseq.c (iseq_load): keep type_map to get rid of memory leak.
+ based on a patch by Eric Wong at [ruby-core:59699]. [Bug #9399]
+
+Fri Feb 14 15:25:23 2014 Tanaka Akira <akr@fsij.org>
+
+ * lib/resolv.rb (Resolv::DNS::Resource::TXT#data): Return concatenated
+ string.
+ Patch by Ryan Brunner. [ruby-core:58220] [Bug #9093]
+
+Fri Feb 14 15:23:43 2014 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket: Avoid unnecessary ppoll/select on Linux.
+ Patch by Eric Wong. [ruby-core:57950] [Bug #9039]
+
+Fri Feb 14 15:21:21 2014 Eric Wong <e@80x24.org>
+
+ * benchmark/driver: avoid large alloc in driver process
+ [ruby-core:59869] [Bug #9430]
+
+Fri Feb 14 15:17:17 2014 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/fiddle/closure.c: use sizeof(*pcl) for correct sizeof value.
+ [ruby-core:57599] [Bug #8978].
+
+Fri Feb 14 15:17:17 2014 Aaron Patterson <aaron@tenderlovemaking.com>
+
+ * ext/fiddle/closure.c: use sizeof(*pcl) for correct sizeof value.
+ [ruby-core:57599] [Bug #8978]. Thanks mame!
+
+Fri Feb 14 15:04:36 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread_pthread.c (rb_thread_create_timer_thread): fix for platforms
+ where PTHREAD_STACK_MIN is a dynamic value and not a compile-time
+ constant. [ruby-dev:47911] [Bug #9436]
+
+Fri Feb 14 15:04:36 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread_pthread.c (rb_thread_create_timer_thread): expand timer
+ thread stack size to get rid of segfault on FreeBSD/powerpc64.
+ based on the patch by Steve Wills at [ruby-core:59923].
+ [ruby-core:56590] [Bug #8783]
+
+Fri Feb 14 14:58:19 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_mod_s_constants): return its own constants for other
+ than Module itself. [ruby-core:59763] [Bug #9413]
+
+Fri Feb 14 14:40:27 2014 Masaki Matsushita <glass.saga@gmail.com>
+
+ * array.c (rb_hash_rehash): use hash_alloc() instead of rb_hash_new().
+ [Bug #9187]
+
+Fri Feb 14 14:40:27 2014 Masaki Matsushita <glass.saga@gmail.com>
+
+ * hash.c (rb_hash_rehash): make temporary st_table under the control
+ of GC. [Bug #9187]
+
+ * test/ruby/test_hash.rb: add a test for above.
+
+Fri Feb 14 14:40:27 2014 Masaki Matsushita <glass.saga@gmail.com>
+
+ * hash.c (rb_hash_rehash): fix to free new st_table when exception
+ is raised in do_hash(). [Bug #9187]
+
+Fri Feb 14 13:51:45 2014 Eric Hodel <drbrain@segment7.net>
+
+ * lib/optparse.rb: The Integer acceptable now allows binary and
+ hexadecimal numbers per the documentation. [ruby-trunk - Bug #8865]
+
+ DecimalInteger, OctalInteger, DecimalNumeric now validate their input
+ before converting to a number. [ruby-trunk - Bug #8865]
+
+ * test/optparse/test_acceptable.rb: Tests for the above, tests for all
+ numeric acceptables for existing behavior.
+
+Fri Feb 14 12:52:50 2014 Kouhei Sutou <kou@cozmixng.org>
+
+ * ext/socket/raddrinfo.c (nogvl_getaddrinfo): Fix indent.
+
+Fri Feb 14 12:52:50 2014 Kouhei Sutou <kou@cozmixng.org>
+
+ * ext/socket/raddrinfo.c (nogvl_getaddrinfo): Add missing return
+ value assignment.
+
+Fri Feb 14 12:52:50 2014 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/socket/raddrinfo.c (nogvl_getaddrinfo): work around for Ubuntu
+ 13.04's getaddrinfo issue with mdns4. [ruby-list:49420]
+
+Fri Feb 14 12:45:07 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/thread.rb (SizedQueue#clear): wake waiting threads when called.
+ [Bug #9342] [ruby-core:59462]
+
+ * test/thread/test_queue.rb: add a test for above.
+
+ patched by Justin Collins.
+
+Thu Feb 6 09:06:00 2014 Kenta Murata <mrkn@cookpad.com>
+
+ * configure.in (POSTLINK): sign built program using RUBY_CODESIGN
+ identity.
+ [Backport #9491]
+
+ * Makefile.in (PROGRAM): ditto.
+
+ * Makefile.in (LIBRUBY_SO): ditto.
+
+ * lib/mkmf.rb (LINK_SO): sign extensions too. replace empty line with
+ default command.
+
+ * enc/depend (link_so): prefix $(Q) for each commands.
+
+ * tool/mkconfig.rb: restore embedded newlines.
+
+Wed Feb 5 13:43:02 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_modify_expand): enable capacity and disable
+ assocation with packed objects when setting capa, so that
+ pack("p") string fails to unpack properly after modified.
+
+Sun Feb 2 05:48:42 2014 Eric Wong <e@80x24.org>
+
+ * io.c (rb_io_syswrite): add RB_GC_GUARD
+ [Bug #9472][ruby-core:60407]
+
+Wed Feb 5 11:36:30 2014 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * configure.in (opt-dir): don't use non portable flag -E of sed.
+
+Thu Jan 30 20:53:42 2014 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/lib/socket.rb: Don't test $! in "ensure" clause because
+ it may be set before the body.
+ Reported by ko1 and mrkn. [ruby-core:59088] [Bug #9247]
+
+ * lib/cgi/core.rb: Ditto.
+
+ * lib/drb/ssl.rb: Ditto.
+
+Thu Jan 30 20:31:32 2014 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * process.c (rb_daemon): daemon(3) is implemented with fork(2).
+ Therefore it needs rb_thread_atfork(). (and revert r41903)
+
+Thu Jan 30 20:31:32 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (fork_daemon): kill the other threads all and abandon the
+ kept mutexes.
+
+Thu Jan 30 20:31:32 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (fork_daemon): kill the other threads all and abandon the
+ kept mutexes.
+
+Thu Jan 30 19:54:16 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (finalize_deferred): flush all deferred finalizers while other
+ finalizers can get ready to run newly by lazy sweep.
+ [ruby-core:58833] [Bug #9205]
+
+Thu Jan 30 19:08:00 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (rb_gc_finalize_deferred, rb_objspace_call_finalizer):
+ should use ATOMIC_EXCHANGE() to check the previous value.
+ [ruby-dev:44596] [Bug #5439]
+
+Thu Jan 30 19:08:00 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (slot_sweep, rb_gc_finalize_deferred)
+ (rb_objspace_call_finalizer, rb_gc): run finalizers
+ sequencially. [ruby-dev:44562]
+
+Thu Jan 30 11:07:09 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c (CLASS_NAME): macro to wrap
+ depending on PRIsVALUE for 1.9. [Backport #9406]
+
+ * ext/bigdecimal/bigdecimal.c (DECIMAL_SIZE_OF_BITS): fallback
+ definition for 2.1 or older. [ruby-core:59750] [Backport #9406]
+
+Wed Jan 29 19:22:45 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enumerator.c: include internal.h instead of declaring the external
+ function there.
+
+Wed Jan 29 18:52:09 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enumerator.c (enumerator_with_index_i): add the declaration of
+ rb_int_succ(). this fixes test failure on OS X introduced at r44745.
+
+Wed Jan 29 14:44:44 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/date/date_strptime.c (date__strptime_internal): unset
+ case-insensitive flag for [:alpha:], which already implies both
+ cases, to get rid of backtrack explosion. [ruby-core:58984]
+ [Bug #9221]
+
+Wed Jan 29 14:44:44 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/date/date_parse.c (parse_time): unset case-insensitive flag
+ for [:alpha:], which already implies both cases, to get rid of
+ backtrack explosion. [ruby-core:58876] [Bug #9221]
+
+Wed Jan 29 14:26:10 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enumerator.c (enumerator_with_index): should not store local variable
+ address to memoise the arguments. it is invalidated after the return.
+ [ruby-core:58692] [Bug #9178]
+
+Wed Jan 29 14:26:10 2014 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * enumerator.c (enumerator_with_index): try to convert given offset to
+ integer. fix bug introduced in r39594.
+
+Wed Jan 29 14:20:11 2014 Eric Hodel <drbrain@segment7.net>
+
+ * enumerator.c (enumerator_with_index): Restore handling of a nil memo
+ from r39594.
+
+Wed Jan 29 14:08:54 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby/win32.h (rb_infinity_float): suppress overflow in
+ constant arithmetic warnings. [ruby-core:57981] [Bug #9044]
+
+Wed Jan 29 14:08:54 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/Makefile.sub (config.h): VC 2013 supports C99 mathematics
+ functions. [ruby-core:57981] [Bug #9044]
+
+Wed Jan 29 14:00:15 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * compar.c (cmp_eq): fail if recursion. [ruby-core:57736] [Bug #9003]
+
+ * thread.c (rb_exec_recursive_paired_outer): new function which is
+ combinnation of paired and outer variants.
+
+Wed Jan 29 13:40:48 2014 Eric Hodel <drbrain@segment7.net>
+
+ * lib/net/smtp.rb (Net::SMTP#critical): Always return a
+ Net::SMTP::Response. Patch by Pawel Veselov.
+ [ruby-trunk - Bug #9125]
+ * test/net/smtp/test_smtp.rb: Test for the above.
+
+Wed Jan 29 13:32:53 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval_jump.c (rb_exec_end_proc): unlink and free procs data before
+ calling for each procs. [Bug #9110]
+
+Wed Jan 29 13:32:53 2014 Masaki Matsushita <glass.saga@gmail.com>
+
+ * eval_jump.c (rb_exec_end_proc): fix double free or corruption error
+ when reentering by callcc. [ruby-core:58329] [Bug #9110]
+
+ * test/ruby/test_beginendblock.rb: test for above.
+
+Wed Jan 29 13:25:32 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/resolv.rb (Resolv::Hosts#lazy_initialize): should not
+ consider encodings in hosts file. [ruby-core:59239] [Bug #9273]
+
+ * lib/resolv.rb (Resolv::Config.parse_resolv_conf): ditto.
+
+Wed Jan 29 13:00:17 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * util.c (ruby_qsort): fix potential stack overflow on a large
+ machine. based on the patch by Conrad Irwin <conrad.irwin AT
+ gmail.com> at [ruby-core:51816]. [Bug #7772]
+
+Wed Jan 29 12:54:13 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (local_push_gen, local_pop_gen): save cmdarg_stack to
+ isolate command argument state from outer scope.
+ [ruby-core:59342] [Bug #9308]
+
+Wed Jan 29 12:37:33 2014 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c (rb_thread_mark): mark a working Proc of bmethod
+ (a method defined by define_method) even if the method was removed.
+ We could not trace working Proc object which represents the body
+ of bmethod if the method was removed (alias/undef/overridden).
+ Simply, it was mark miss.
+ This patch by Kazuki Tsujimoto. [Bug #7825]
+
+ NOTE: We can brush up this marking because we do not need to mark
+ `me' on each living control frame. We need to mark `me's
+ only if `me' was free'ed. This is future work after Ruby 2.0.0.
+
+ * test/ruby/test_method.rb: add a test.
+
+Wed Jan 29 12:35:37 2014 CHIKANAGA Tomoyuki <nagachika@ruby-lang.org>
+
+ * lib/rexml/document.rb (REXML::Document.entity_expansion_text_limit):
+ fix a typo in comment in r39384.
+
+Thu Jan 9 14:27:25 2014 Aman Gupta <ruby@tmm1.net>
+
+ * test/net/imap/cacert.pem: generate new CA cert, since the last one
+ expired. [Bug #9341] [ruby-core:59459]
+ * test/net/imap/server.crt: new server cert signed with updated CA.
+ * test/net/imap/Makefile: add `make regen_certs` to automate this
+ process.
+
+Sun Dec 22 14:25:54 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * process.c (redirect_dup2): set standard handles when new fd is stdio,
+ because if there is no allocated console at the moment Windows does
+ not automatically associate it for child process's standard handle.
+ this is adhoc workaround.
+ reported by Martin Thiede at [ruby-core:48542] [Bug #7239].
+
+Tue Dec 3 18:36:42 2013 Narihiro Nakamura <authornari@gmail.com>
+
+ * object.c (rb_obj_clone): protect FL_MARK of a dest object. A lazy
+ sweeper free up a dest object if a marker is invoked immediately
+ following allocate a dest object in rb_obj_alloc().
+ [Backport #9206]
+
+Sun Dec 22 13:35:58 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/rubygems.rb: 1.8.23.2.
+ [ruby-core:58757] [Backport#9193] reported by Jeremy Evans and patched
+ by Eric Hodel.
+
+Fri Nov 22 12:44:56 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * util.c (ruby_strtod): ignore too long fraction part, which does not
+ affect the result.
+
+Fri Nov 1 00:08:21 2013 Martin Bosslet <Martin.Bosslet@gmail.com>
+
+ * test/openssl/test_pkey_ec.rb: Skip tests for "Oakley" curves as
+ they are not suitable for ECDSA.
+ [ruby-core:54881] [Bug #8384]
+
+Fri Nov 1 00:04:17 2013 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
+
+ * parse.y: Remove +(binary) and -(binary) special cases
+ [Feature #9048]
+
+Thu Oct 31 23:57:22 2013 Benoit Daloze <eregontp@gmail.com>
+
+ * test/ruby/test_array.rb (test_count): add a test case for #count
+ with an argument. See Bug #8654.
+
+Thu Oct 31 23:57:22 2013 Benoit Daloze <eregontp@gmail.com>
+
+ * array.c (rb_ary_count): check length to avoid SEGV
+ while iterating. Remove other pointer loop when arg is given.
+
+ * test/ruby/test_array.rb (test_count): add test for bug.
+ [ruby-core:56072] [Bug #8654]
+
+Thu Oct 31 23:57:22 2013 Masaki Matsushita <glass.saga@gmail.com>
+
+ * array.c (rb_ary_count): iterate items appropriately.
+ [Bug #8654]
+
+Thu Oct 31 23:42:39 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/tempfile.rb (Tempfile#unlink): finalizer is no longer needed
+ after unlinking. patched by by normalperson (Eric Wong) at
+ [ruby-core:56521] [Bug #8768]
+
+Thu Oct 31 23:40:43 2013 Zachary Scott <e@zzak.io>
+
+ * lib/gserver.rb: [DOC] correct gserver.rb license [Bug #8913]
+
+Thu Oct 31 23:35:12 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vsnprintf.c (MAXEXP, MAXFRACT): calculate depending on constants in
+ float.h.
+
+ * vsnprintf.c (BSD_vfprintf): limit length for cvt() to get rid of
+ buffer overflow. [ruby-core:57023] [Bug #8864]
+
+ * vsnprintf.c (exponent): make expbuf size more precise.
+
+Thu Oct 31 23:32:41 2013 Michal Rokos <michal@rokos.cz>
+
+ * configure.in (sys/pstat.h): fix missing header check for
+ missing/setproctitle.c on HP-UX. [ruby-core:56644] [Bug #8792]
+
+Thu Oct 31 23:25:25 2013 Martin Bosslet <Martin.Bosslet@gmail.com>
+
+ * ext/openssl/ossl_pkey_ec.c: Ensure compatibility to builds of
+ OpenSSL with OPENSSL_NO_EC2M defined, but OPENSSL_NO_EC not
+ defined.
+ * test/openssl/test_pkey_ec.rb: Iterate over built-in curves
+ (and assert their non-emptiness!) instead of hard-coding them, as
+ this may cause problems with respect to the different availability
+ of individual curves in individual OpenSSL builds.
+ [ruby-core:54881] [Bug #8384]
+
+ Thanks to Vit Ondruch for providing the patch!
+
+Thu Oct 31 23:22:35 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * object.c (rb_obj_cmp): [DOC] patched by Keith Bennett
+ <kbennett AT verisign.com>. [ruby-core:57887] [Backport #9024]
+
+Thu Oct 31 23:10:30 2013 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ * test/dl/test_base.rb: {libc, libm} detection now handle GNU/Hurd
+ correctly. Patch by Gabriele Giacone (1o5g4r8o@gmail.com).
+ [Bug #8937][ruby-core:57311]
+ * test/fiddle/helper.rb: ditto.
+
+Thu Oct 31 23:05:33 2013 Tanaka Akira <akr@fsij.org>
+
+ * lib/time.rb (Time.strptime): Time.strptime('0', '%s') returns local
+ time Time object as Ruby 2.0 and before.
+
+Thu Oct 31 23:05:33 2013 Tanaka Akira <akr@fsij.org>
+
+ * lib/time.rb (Time.strptime): Use :offset.
+ Patch by Felipe Contreras. [ruby-core:57694]
+
+Thu Oct 31 22:49:56 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_close_read): duplex IO should wait its child process
+ even after close_read.
+
+Thu Oct 31 22:49:56 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_close_read): keep fptr in write_io to be discarded, to
+ fix freed pointer access when it is in use by other threads, and get
+ rid of potential memory/fd leak.
+
+Mon Sep 2 17:21:47 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/date/date_parse.c (rfc2822_cb): check if wday is given, since it
+ can be omitted.
+
+Mon Aug 19 18:36:37 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/webrick/test_cgi.rb (TestWEBrickCGI#{start_cgi_server,test_cgi}):
+ mswin is not only mswin32 but also mswin64. [Bug #8746]
+
+Mon Aug 19 18:34:31 2013 Charlie Somerville <charliesome@ruby-lang.org>
+
+ * test/openssl/test_ssl.rb: Fix test for CVE-2013-4073.
+ Patch by Antonio Terceiro. [Bug #8750] [ruby-core:56437]
+
+Mon Aug 19 18:31:26 2013 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * parse.y: fix build error with bison-3.0.
+
+Fri Aug 16 15:35:10 2013 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * ext/date/date_{core,strftime}.c: [ruby-core:46990].
+
+Wed Aug 14 09:56:55 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (have_framework): allow header file to check.
+ [ruby-core:55745] [Bug #8593]
+
+Fri Aug 9 16:29:22 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (xsystem): expand environment variable in all macros not
+ expanded with RbConfig. [Bug #8702]
+
+ * test/mkmf/test_framework.rb (create_framework): replace all $@ not
+ only once.
+
+Fri Aug 9 15:59:22 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (parser_peek_variable_name): treat invalid global, class,
+ and instance variable names as mere strings rather than errors.
+ [ruby-core:54885] [Bug #8375]
+
+Fri Aug 9 15:59:22 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (parser_yylex): fail if $, @, @@ are not followed by a valid
+ name character. [ruby-core:54846] [Bug #8375].
+
+Fri Aug 9 15:56:05 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/net/http.rb (Net::HTTP#send_request_with_body_stream): use
+ String#bytesize instead of String#length.
+ reported by shekhei (shek hei wong) at [ruby-core:53775]
+ [Backport #8176].
+
+Fri Aug 9 15:50:11 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (wrename): use MoveFileExW instead of MoveFileW,
+ because the latter fails on cross device file move of some
+ environments.
+ fix [ruby-core:53492] [Bug #8109]
+ reported by mitchellh (Mitchell Hashimoto)
+
+Thu Aug 8 16:09:26 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/coverage/test_coverage.rb (TestCoverage#test_big_code): use `1'
+ instead of `p' to get rid of a side effect.
+ Kernel#p without any argument seems to do nothing, but flushes stdout.
+ and, if stdout is redirected to file, fsync() will be called on
+ Windows. so, when running test-all on Windows with redirection, such
+ as CI environment, this test took a lot of time.
+
+Fri Aug 2 20:41:15 2013 Eric Hodel <drbrain@segment7.net>
+
+ * ext/openssl/ossl_asn1.c (asn1time_to_time): Implement YYMMDDhhmmZ
+ format for ASN.1 UTCTime. [ruby-trunk - Bug #8664]
+ * test/openssl/test_asn1.rb: Test for the above.
+
+Fri Aug 2 20:34:06 2013 Masaki Matsushita <glass.saga@gmail.com>
+
+ * io.c (io_getpartial): use rb_str_locktmp_ensure().
+ [ruby-core:56121] [Bug #8669]
+
+ * io.c (rb_io_sysread): ditto.
+
+ * test/ruby/test_io.rb: add tests for above.
+
+Fri Aug 2 20:34:06 2013 Masaki Matsushita <glass.saga@gmail.com>
+
+ * string.c: add internal API rb_str_locktmp_ensure().
+
+ * io.c (io_fread): use rb_str_locktmp_ensure().
+ [ruby-core:56121] [Bug #8669]
+
+ * test/ruby/test_io.rb: add a test for above.
+
+Fri Aug 2 20:03:39 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * rational.c (f_round_common): Rational is expected to be returned by
+ Rational#*, but mathn.rb breaks that assumption. [ruby-core:56177]
+ [Bug #8687]
+
+Wed Jul 17 11:00:21 2013 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * ext/date/date_core.c: [ruby-core:46058].
+
+Wed Jul 17 10:14:37 2013 Martin Bosslet <Martin.Bosslet@gmail.com>
+
+ * lib/openssl/ssl-internal.rb: Fix SSL client connection crash for SAN
+ marked critical.
+ The patch for CVE-2013-4073 caused SSL crash when a SSL server returns
+ the certificate that has critical SAN value. X509 extension could
+ include 2 or 3 elements in it:
+
+ [id, criticality, octet_string] if critical,
+ [id, octet_string] if not.
+
+ Making sure to pick the last element of X509 extension and use it as
+ SAN value.
+ [ruby-core:55685] [Bug #8575]
+
+ Thank you @nahi for providing the patch!
+
+Wed Jul 17 09:59:33 2013 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * ext/date/date_core.c: fixed coding error [ruby-core:55337].
+ reported by Riley Lynch.
+
+Wed Jul 17 09:59:33 2013 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * ext/date/date_core.c: fixed a bug [ruby-core:55295]. reported
+ by Riley Lynch.
+
+Thu Jul 11 10:07:15 2013 Kenta Murata <mrkn@mrkn.jp>
+
+ * ext/bigdecimal/bigdecimal.c (BigMath_s_exp): Fix for the cases when
+ the argument x is not a BigDecimal.
+ This change is based on the patch made by Heesob Park and Garth Snyder.
+ [Bug #6862] [ruby-core:47145]
+ [Fix GH-332] https://github.com/ruby/ruby/pull/332
+
+Wed Jul 10 10:27:12 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * include/ruby/intern.h (rb_path_next, rb_path_skip_prefix,
+ rb_path_last_separator, rb_path_end, ruby_find_basename,
+ ruby_find_extname): restore the declarations of these functions for
+ backword compatibility.
+
+ * filc.c (rb_path_next, rb_path_skip_prefix, rb_path_last_separator,
+ rb_path_end, ruby_find_basename, ruby_find_extname): implements
+ these functions as the wrapper of rb_enc_*().
+
+Wed Jul 10 10:05:40 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * include/ruby/intern.h (rb_f_lambda): restore the declaration of
+ rb_f_lambda() for backword compatibility.
+
+Thu Jun 27 20:11:52 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/openssl/lib/openssl/ssl-inernal.rb (verify_certificate_identity):
+ fix hostname verification. Patched by nahi.
+
+ * test/openssl/test_ssl.rb (test_verify_certificate_identity): test for
+ above.
+
+Wed Jun 26 18:28:29 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/ruby/test_m17n.rb: assert_predicate and assert_not_predicate
+ is not available on 1.9.3.
+
+Wed Jun 26 17:08:13 2013 Kazuki Tsujimoto <kazuki@callcc.net>
+
+ * include/ruby/ruby.h, vm_eval.c (rb_funcall_with_block):
+ new function to invoke a method with a block passed
+ as an argument.
+
+ * string.c (sym_call): use the above function to avoid
+ a block sharing. [ruby-dev:47438] [Bug #8531]
+
+ * vm_insnhelper.c (vm_yield_with_cfunc): don't set block
+ in the frame.
+
+ * test/ruby/test_symbol.rb (TestSymbol#test_block_given_to_proc):
+ run related tests.
+
+Wed Jun 26 17:01:22 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * benchmark/bm_hash_shift.rb: add benchmark for Hash#shift
+
+ * hash.c (rb_hash_shift): use st_shift if hash is not being iterated to
+ delete element without iterating the whole hash.
+
+ * hash.c (shift_i): remove function
+
+ * include/ruby/st.h (st_shift): add st_shift function
+
+ * st.c (st_shift): ditto
+
+ [Backport #8328] [ruby-core:55250] Patch by funny-falcon
+
+Wed Jun 26 16:52:57 2013 Kazuki Tsujimoto <kazuki@callcc.net>
+
+ * test/ruby/test_proc.rb (TestProc#test_block_given_method_to_proc):
+ run test for r41359.
+
+Wed Jun 26 16:52:57 2013 Kazuki Tsujimoto <kazuki@callcc.net>
+
+ * include/ruby/intern.h, proc.c (rb_method_call_with_block):
+ new function to invoke a Method object with a block passed
+ as an argument.
+
+ * proc.c (bmcall): use the above function to avoid a block sharing.
+ [ruby-core:54626] [Bug #8341]
+
+ * test/ruby/test_proc.rb (TestProc#test_block_persist_between_calls):
+ run related tests.
+
+Wed Jun 26 16:36:39 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * defs/id.def (predefined): add "idProc".
+
+ * proc.c (mnew, mproc, mlambda): use predefined IDs.
+
+ * vm.c (Init_VM): ditto.
+
+Wed Jun 26 16:36:39 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby/intern.h (rb_block_lambda): add declaration instead of
+ deprecated rb_f_lambda.
+
+Wed Jun 26 16:31:49 2013 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (capability_response): should ignore trailing
+ spaces. Thanks, Peter Kovacs. [ruby-core:55024] [Bug #8415]
+
+ * test/net/imap/test_imap_response_parser.rb: related test.
+
+Wed Jun 26 16:29:41 2013 Charlie Somerville <charliesome@ruby-lang.org>
+
+ * intern.h: remove dangling rb_class_init_copy declaration
+ [ruby-core:55120] [Bug #8434]
+
+Wed Jun 26 16:22:12 2013 Charlie Somerville <charliesome@ruby-lang.org>
+
+ * class.c (include_modules_at): invalidate method cache if included
+ module contains constants
+
+ * test/ruby/test_module.rb: add test
+
+Wed Jun 26 16:13:25 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (io_getc): fix 7bit coderange condition, check if ascii read
+ data instead of read length. [ruby-core:55444] [Bug #8516]
+
+Wed Jun 26 16:10:01 2013 Eric Hodel <drbrain@segment7.net>
+
+ * ext/socket/extconf.rb: Enable RFC 3542 IPV6 socket options for OS X
+ 10.7+. [ruby-trunk - Bug #8517]
+
+Wed Jun 5 12:38:14 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (setup_overlapped, finish_overlapped): extract from
+ rb_w32_read() and rb_w32_write().
+
+Wed May 29 21:03:08 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (POSTLINK): default to : command to get rid of flag
+ only command, since BSD make does not work with it.
+
+Wed May 29 20:59:38 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/yaml.rb: documentation updates, patched by zzak.
+ [ruby-core:54735] [Backport #8356]
+
+Wed May 15 14:04:39 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * Makefile.in (miniruby): 1.9.3 doesn't have POSTLINK macro.
+ reported by Takahiro Kambe at [ruby-list:49362].
+
+Wed May 15 01:06:26 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * include/ruby/intern.h: should include sys/time.h for struct timeval
+ if it exists.
+
+Wed May 15 00:23:07 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (warnflags): disable -Werror by default unless
+ development. [ruby-core:52131] [Bug #7830]
+
+Wed May 15 00:21:31 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * signal.c: need to include unistd.h for write(2).
+
+Tue May 14 20:25:58 2013 CHIKANAGA Tomoyuki <nagachika@ruby-lang.org>
+
+ * ext/dl/lib/dl/func.rb (DL::Function#call): check tainted when
+ $SAFE > 0.
+ * ext/fiddle/function.c (function_call): check tainted when $SAFE > 0.
+ * test/fiddle/test_func.rb (module Fiddle): add test for above.
+
+
+Tue May 14 11:36:22 2013 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (getacl_response): parse the mailbox of an ACL
+ response correctly. [ruby-core:54365] [Bug #8281]
+
+Tue May 14 11:24:22 2013 Martin Bosslet <Martin.Bosslet@gmail.com>
+
+ * ext/openssl/ossl_ssl.c: Correct shutdown behavior w.r.t GC.
+
+ * test/openssl/test_ssl.rb: Add tests to verify correct behavior.
+
+ [Bug #8240] Patch provided by Shugo Maeda. Thanks!
+
+Tue May 14 11:22:33 2013 Naohisa Goto <ngotogenome@gmail.com>
+
+ * configure.in (AC_CHECK_HEADERS): atomic.h for Solaris atomic_ops.
+
+ * ruby_atomic.h: Skip using Solaris10 atomic_ops on Solaris 9 or
+ earlier if atomic.h is not available. [ruby-dev:47229] [Bug #8228]
+
+Tue May 14 10:42:23 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (MAIN_DOES_NOTHING): ensure symbols for tests to be
+ preserved. [ruby-core:53745] [Bug #8169]
+
+Tue May 14 10:42:23 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (MAIN_DOES_NOTHING): force to refer symbols for tests
+ to be preserved. [ruby-core:53745] [Bug #8169]
+
+Tue May 14 10:39:33 2013 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * regexec.c (onig_search): fix problem with optimization of \z.
+ [Backport #8210]
+ patched by k_takata at [ruby-core:54251].
+
+Tue May 14 09:36:14 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (GetTimeval): check if already initialized instance.
+
+ * time.c (GetNewTimeval): check if newly created instance.
+
+ * time.c (time_init_0, time_init_1, time_init_copy, time_mload): must
+ be newly created instance. [ruby-core:53436] [Bug #8099]
+
Thu Apr 11 11:24:42 2013 Akinori MUSHA <knu@iDaemons.org>
* lib/ipaddr.rb (IPAddr#in6_addr): Fix a typo with the closing
diff --git a/Makefile.in b/Makefile.in
index 9c25d24729..680f761c5f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -71,6 +71,7 @@ ARCHMINIOBJS = @MINIOBJS@
BUILTIN_ENCOBJS = @BUILTIN_ENCOBJS@
BUILTIN_TRANSSRCS = @BUILTIN_TRANSSRCS@
BUILTIN_TRANSOBJS = @BUILTIN_TRANSOBJS@
+POSTLINK = @POSTLINK@
RUBY_BASE_NAME=@RUBY_BASE_NAME@
RUBY_PROGRAM_VERSION=@RUBY_PROGRAM_VERSION@
@@ -185,6 +186,7 @@ $(LIBRUBY_SO):
$(ECHO) linking shared-library $@
$(Q) $(LDSHARED) $(DLDFLAGS) $(OBJS) $(DLDOBJS) $(SOLIBS) $(OUTFLAG)$@
-$(Q) $(OBJCOPY) -w -L '$(SYMBOL_PREFIX)Init_*' -L '$(SYMBOL_PREFIX)*_threadptr_*' $@
+ $(Q) $(POSTLINK)
@-$(MINIRUBY) -e 'ARGV.each{|link| File.delete link if File.exist? link; \
File.symlink "$(LIBRUBY_SO)", link}' \
$(LIBRUBY_ALIASES) || true
diff --git a/array.c b/array.c
index e427cb3320..73f7669f94 100644
--- a/array.c
+++ b/array.c
@@ -3692,27 +3692,28 @@ rb_ary_compact(VALUE ary)
static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
- long n = 0;
+ long i, n = 0;
if (argc == 0) {
- VALUE *p, *pend;
+ VALUE v;
if (!rb_block_given_p())
return LONG2NUM(RARRAY_LEN(ary));
- for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
- if (RTEST(rb_yield(*p))) n++;
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ v = RARRAY_PTR(ary)[i];
+ if (RTEST(rb_yield(v))) n++;
}
}
else {
- VALUE obj, *p, *pend;
+ VALUE obj;
rb_scan_args(argc, argv, "1", &obj);
if (rb_block_given_p()) {
rb_warn("given block not used");
}
- for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
- if (rb_equal(*p, obj)) n++;
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ if (rb_equal(RARRAY_PTR(ary)[i], obj)) n++;
}
}
diff --git a/benchmark/driver.rb b/benchmark/driver.rb
index 7dab292a15..4028110659 100644
--- a/benchmark/driver.rb
+++ b/benchmark/driver.rb
@@ -220,7 +220,7 @@ class BenchmarkDriver
def measure executable, file
cmd = "#{executable} #{file}"
m = Benchmark.measure{
- `#{cmd}`
+ system(cmd, out: File::NULL)
}
if $? != 0
diff --git a/bignum.c b/bignum.c
index 85f739d2bb..2f0eca7fca 100644
--- a/bignum.c
+++ b/bignum.c
@@ -2729,7 +2729,7 @@ bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
if (modp) { /* normalize remainder */
*modp = zz = rb_big_clone(z);
zds = BDIGITS(zz);
- while (--ny && !zds[ny]); ++ny;
+ while (ny > 1 && !zds[ny-1]) --ny;
if (dd) {
t2 = 0; i = ny;
while(i--) {
diff --git a/class.c b/class.c
index 4fbdf18fb7..ca029895ea 100644
--- a/class.c
+++ b/class.c
@@ -180,6 +180,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
if (RB_TYPE_P(clone, T_CLASS)) {
class_init_copy_check(clone, orig);
}
+ if (clone == orig) return clone;
rb_obj_init_copy(clone, orig);
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
RBASIC(clone)->klass = rb_singleton_class_clone(orig);
@@ -699,6 +700,8 @@ rb_include_module(VALUE klass, VALUE module)
c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
changed = 1;
+ if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries)
+ changed = 1;
skip:
module = RCLASS_SUPER(module);
}
diff --git a/common.mk b/common.mk
index ccc964701e..b26ba729c3 100644
--- a/common.mk
+++ b/common.mk
@@ -619,7 +619,8 @@ encoding.$(OBJEXT): {$(VPATH)}encoding.c $(RUBY_H_INCLUDES) \
{$(VPATH)}internal.h
enum.$(OBJEXT): {$(VPATH)}enum.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h \
{$(VPATH)}util.h $(ID_H_INCLUDES)
-enumerator.$(OBJEXT): {$(VPATH)}enumerator.c $(RUBY_H_INCLUDES)
+enumerator.$(OBJEXT): {$(VPATH)}enumerator.c $(RUBY_H_INCLUDES) \
+ {$(VPATH)}node.h {$(VPATH)}internal.h
error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}known_errors.inc \
$(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) $(ENCODING_H_INCLUDES) \
{$(VPATH)}debug.h \
diff --git a/compar.c b/compar.c
index 65def78484..b7d4f9c937 100644
--- a/compar.c
+++ b/compar.c
@@ -32,9 +32,16 @@ rb_cmperr(VALUE x, VALUE y)
}
static VALUE
+cmp_eq_recursive(VALUE arg1, VALUE arg2, int recursive)
+{
+ if (recursive) return Qfalse;
+ return rb_funcall2(arg1, cmp, 1, &arg2);
+}
+
+static VALUE
cmp_eq(VALUE *a)
{
- VALUE c = rb_funcall(a[0], cmp, 1, a[1]);
+ VALUE c = rb_exec_recursive_paired_outer(cmp_eq_recursive, a[0], a[1], a[1]);
if (NIL_P(c)) return Qfalse;
if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
diff --git a/configure.in b/configure.in
index accaf9ee3b..afdb77c45a 100644
--- a/configure.in
+++ b/configure.in
@@ -83,6 +83,7 @@ RUBY_PROGRAM_VERSION=`sed -n 's/^#define RUBY_VERSION "\(.*\)"/\1/p' $srcdir/ver
AC_SUBST(RUBY_PROGRAM_VERSION)
RUBY_RELEASE_DATE=`sed -n 's/^#define RUBY_RELEASE_DATE "\(.*\)"/\1/p' $srcdir/version.h`
AC_SUBST(RUBY_RELEASE_DATE)
+RUBY_PATCHLEVEL=`sed -n 's/^#define RUBY_PATCHLEVEL //p' $srcdir/version.h`
if test "$MAJOR" = "1"; then
AC_DEFINE(CANONICALIZATION_FOR_MATHN)
fi
@@ -307,6 +308,29 @@ if test "$target_cpu" != "$host_cpu" -a "$GCC" = yes -a "$cross_compiling" = no
RUBY_DEFAULT_ARCH("$target_cpu")
fi
+AS_CASE(["$target_cpu-$target_os"], [[i[3-6]86*]], [
+ AC_CACHE_CHECK([for __sync_val_compare_and_swap], [rb_cv_gcc_compiler_cas], [
+ AC_TRY_LINK([unsigned long atomic_var;],
+ [
+ __sync_val_compare_and_swap(&atomic_var, 0, 1);
+ ],
+ [rb_cv_gcc_compiler_cas=yes],
+ [rb_cv_gcc_compiler_cas=no])])
+ if test "$rb_cv_gcc_compiler_cas" = no; then
+ unset rb_cv_gcc_compiler_cas
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -march=i486"
+ AC_CACHE_CHECK([for __sync_val_compare_and_swap with -march=i486], [rb_cv_gcc_compiler_cas], [
+ AC_TRY_LINK([unsigned long atomic_var;],
+ [
+ __sync_val_compare_and_swap(&atomic_var, 0, 1);
+ ],
+ [rb_cv_gcc_compiler_cas=yes
+ ARCH_FLAG="-march=i486"],
+ [rb_cv_gcc_compiler_cas=no])])
+ CFLAGS="$save_CFLAGS"
+ fi])
+
AC_CHECK_TOOL(RANLIB, ranlib, :)
AC_CHECK_TOOL(AR, ar)
if test -z "$AR"; then
@@ -453,20 +477,26 @@ AC_DEFUN(RUBY_TRY_LDFLAGS, [
save_LDFLAGS=
])
+AS_CASE([$RUBY_PATCHLEVEL], [-*],
+ [particular_werror_flags=yes], [particular_werror_flags=no])
+AC_ARG_ENABLE(werror,
+ AS_HELP_STRING([--disable-werror],
+ [don't make warnings into errors
+ even if a compiler support -Werror feature
+ [[disabled by default unless development version]]]),
+ [particular_werror_flags=$enableval])
+
rb_cv_warnflags="$warnflags"
if test "$GCC:${warnflags+set}:no" = yes::no; then
- particular_werror_flags=yes
for wflag in -Wno-unused-parameter -Wno-parentheses -Wno-long-long \
-Wno-missing-field-initializers \
-Werror=pointer-arith \
-Werror=write-strings \
-Werror=declaration-after-statement \
-Werror=shorten-64-to-32 \
- -Werror-implicit-function-declaration \
+ -Werror=implicit-function-declaration \
; do
- if test "$particular_werror_flags" = yes; then
- wflag=`echo x$wflag | sed 's/^x-Werror-/-Werror=/;s/^x//'`
- else
+ if test "$particular_werror_flags" != yes; then
wflag=`echo x$wflag | sed 's/^x-Werror=/-W/;s/^x//'`
fi
ok=no
@@ -880,19 +910,35 @@ if test "$GCC" = yes; then
AC_DEFINE_UNQUOTED([RUBY_ALIAS_FUNCTION_VOID(prot, name, args)],
[RUBY_ALIAS_FUNCTION_TYPE(void, prot, name, args)])
fi
- AC_CACHE_CHECK([for atomic builtins], [rb_cv_gcc_atomic_builtins], [
+
+ AC_CACHE_CHECK([for __atomic builtins], [rb_cv_gcc_atomic_builtins], [
AC_TRY_LINK([unsigned char atomic_var;],
[
- __sync_lock_test_and_set(&atomic_var, 0);
- __sync_lock_test_and_set(&atomic_var, 1);
- __sync_fetch_and_add(&atomic_var, 1);
- __sync_fetch_and_sub(&atomic_var, 1);
+ __atomic_exchange_n(&atomic_var, 0, __ATOMIC_SEQ_CST);
+ __atomic_exchange_n(&atomic_var, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&atomic_var, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_sub(&atomic_var, 1, __ATOMIC_SEQ_CST);
],
[rb_cv_gcc_atomic_builtins=yes],
[rb_cv_gcc_atomic_builtins=no])])
if test "$rb_cv_gcc_atomic_builtins" = yes; then
AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS)
fi
+
+ AC_CACHE_CHECK([for __sync builtins], [rb_cv_gcc_sync_builtins], [
+ AC_TRY_LINK([unsigned char atomic_var;],
+ [
+ __sync_lock_test_and_set(&atomic_var, 0);
+ __sync_lock_test_and_set(&atomic_var, 1);
+ __sync_fetch_and_add(&atomic_var, 1);
+ __sync_fetch_and_sub(&atomic_var, 1);
+ ],
+ [rb_cv_gcc_sync_builtins=yes],
+ [rb_cv_gcc_sync_builtins=no])])
+ if test "$rb_cv_gcc_sync_builtins" = yes; then
+ AC_DEFINE(HAVE_GCC_SYNC_BUILTINS)
+ fi
+
fi
AC_CACHE_CHECK(for exported function attribute, rb_cv_func_exported, [
@@ -948,6 +994,8 @@ AC_ARG_ENABLE(pthread,
dnl Checks for libraries.
AS_CASE(["$target_os"],[*bsd*|dragonfly*],[],[ac_cv_func_daemon=no])
+POSTLINK=:
+AC_SUBST(POSTLINK)
AS_CASE(["$target_os"],
[solaris*], [
AC_DEFINE(SIZEOF_STRUCT_DIRENT_TOO_SMALL, 1)
@@ -1013,6 +1061,12 @@ main()
if test "$rb_cv_broken_crypt" = yes; then
AC_DEFINE(BROKEN_CRYPT, 1)
fi
+ AC_CHECK_PROGS(codesign, codesign)
+ if test -n "$codesign"; then
+ POSTLINK="test -z '\$(RUBY_CODESIGN)' || $codesign -s '\$(RUBY_CODESIGN)' -f \$@"
+ LINK_SO="$LINK_SO
+\$(POSTLINK)"
+ fi
],
[hpux*], [ LIBS="-lm $LIBS"
ac_cv_c_inline=no],
@@ -1169,7 +1223,7 @@ AC_CHECK_HEADERS(limits.h sys/file.h sys/ioctl.h sys/syscall.h\
syscall.h pwd.h grp.h a.out.h utime.h direct.h sys/resource.h \
sys/mkdev.h sys/utime.h xti.h netinet/in_systm.h float.h ieeefp.h \
ucontext.h intrinsics.h langinfo.h locale.h sys/sendfile.h time.h \
- net/socket.h sys/socket.h process.h)
+ net/socket.h sys/socket.h process.h atomic.h)
AC_TYPE_SIZE_T
RUBY_CHECK_SIZEOF(size_t, [int long void*], [], [@%:@include <sys/types.h>])
@@ -1350,6 +1404,7 @@ AS_CASE(["$target_os"],
[aix* | k*bsd*-gnu | kopensolaris*-gnu | linux* | darwin*], [AC_DEFINE(SPT_TYPE,SPT_REUSEARGV)],
[hpux*], [AC_DEFINE(SPT_TYPE,SPT_PSTAT) ],
[])
+AC_CHECK_HEADERS(sys/pstat.h)
AC_CACHE_CHECK(for signbit, rb_cv_have_signbit,
@@ -2918,7 +2973,7 @@ AC_ARG_WITH(opt-dir,
val=`IFS="$PATH_SEPARATOR"
for dir in $withval; do
echo x ${LIBPATHFLAG} ${RPATHFLAG} |
- sed -E 's/^x *//;s'"${PATH_SEPARATOR}"'%1\\$-s|%s'"${IFS}${dir}/lib${IFS}g"
+ sed "s/^x *//;s${IFS}"'%1\\$-s'"${IFS}${dir}/lib${IFS}g;s${IFS}%s${IFS}${dir}/lib${IFS}g"
done | tr '\012' ' '`
set +x
LDFLAGS="$LDFLAGS${LDFLAGS:+ }$val"
diff --git a/enc/depend b/enc/depend
index 8e930d5053..d42aa5c775 100644
--- a/enc/depend
+++ b/enc/depend
@@ -103,7 +103,7 @@ $(TRANSOBJS): ruby.h intern.h config.h defines.h missing.h encoding.h oniguruma.
% end
% end
-% link_so = LINK_SO.gsub(/\n/, "\n\t")
+% link_so = LINK_SO.gsub(/([^\\])\n/, "\\1\n$(Q) ").gsub(/\n/, "\n\t")
% link_so.gsub!(/(-(?:implib|pdb):\S+)-\$\(arch\)\./, '\1.')
% dependencies.each do |e|
% obj = "enc/#{e}.$(OBJEXT)"
diff --git a/enumerator.c b/enumerator.c
index 09ef298396..bf0abf62f2 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -13,6 +13,8 @@
************************************************/
#include "ruby/ruby.h"
+#include "node.h"
+#include "internal.h"
/*
* Document-class: Enumerator
@@ -368,11 +370,9 @@ enumerator_each(VALUE obj)
static VALUE
enumerator_with_index_i(VALUE val, VALUE m, int argc, VALUE *argv)
{
- VALUE idx;
- VALUE *memo = (VALUE *)m;
-
- idx = INT2FIX(*memo);
- ++*memo;
+ NODE *memo = (NODE *)m;
+ VALUE idx = memo->u1.value;
+ memo->u1.value = rb_int_succ(idx);
if (argc <= 1)
return rb_yield_values(2, val, idx);
@@ -399,8 +399,11 @@ enumerator_with_index(int argc, VALUE *argv, VALUE obj)
rb_scan_args(argc, argv, "01", &memo);
RETURN_ENUMERATOR(obj, argc, argv);
- memo = NIL_P(memo) ? 0 : (VALUE)NUM2LONG(memo);
- return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)&memo);
+ if (NIL_P(memo))
+ memo = INT2FIX(0);
+ else
+ memo = rb_to_int(memo);
+ return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)NEW_MEMO(memo, 0, 0));
}
/*
diff --git a/eval.c b/eval.c
index 9ceb833d37..92b02f73fa 100644
--- a/eval.c
+++ b/eval.c
@@ -313,8 +313,8 @@ rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
VALUE cbase = 0;
void *data = 0;
- if (argc > 0) {
- return rb_mod_constants(argc, argv, rb_cModule);
+ if (argc > 0 || mod != rb_cModule) {
+ return rb_mod_constants(argc, argv, mod);
}
while (cref) {
diff --git a/eval_jump.c b/eval_jump.c
index f3a1f78a3f..4f39374a20 100644
--- a/eval_jump.c
+++ b/eval_jump.c
@@ -96,7 +96,8 @@ rb_mark_end_proc(void)
void
rb_exec_end_proc(void)
{
- struct end_proc_data *volatile link;
+ struct end_proc_data volatile endproc;
+ struct end_proc_data volatile *link;
int status;
volatile int safe = rb_safe_level();
rb_thread_t *th = GET_THREAD();
@@ -105,6 +106,9 @@ rb_exec_end_proc(void)
while (ephemeral_end_procs) {
link = ephemeral_end_procs;
ephemeral_end_procs = link->next;
+ endproc = *link;
+ xfree((void *)link);
+ link = &endproc;
PUSH_TAG();
if ((status = EXEC_TAG()) == 0) {
@@ -116,12 +120,14 @@ rb_exec_end_proc(void)
error_handle(status);
if (!NIL_P(th->errinfo)) errinfo = th->errinfo;
}
- xfree(link);
}
while (end_procs) {
link = end_procs;
end_procs = link->next;
+ endproc = *link;
+ xfree((void *)link);
+ link = &endproc;
PUSH_TAG();
if ((status = EXEC_TAG()) == 0) {
@@ -133,8 +139,8 @@ rb_exec_end_proc(void)
error_handle(status);
if (!NIL_P(th->errinfo)) errinfo = th->errinfo;
}
- xfree(link);
}
+
rb_set_safe_level_force(safe);
th->errinfo = errinfo;
}
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 14f80b1929..c9ff9406b6 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -102,6 +102,15 @@ bigzero_p(VALUE x)
# define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0)))
#endif
+#ifdef PRIsVALUE
+# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
+# define RB_OBJ_STRING(obj) (obj)
+#else
+# define PRIsVALUE "s"
+# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
+# define RB_OBJ_STRING(obj) StringValueCStr(obj)
+#endif
+
/*
* ================== Ruby Interface part ==========================
*/
@@ -2355,7 +2364,9 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
/* fall through */
case T_RATIONAL:
if (NIL_P(nFig)) {
- rb_raise(rb_eArgError, "can't omit precision for a Rational.");
+ rb_raise(rb_eArgError,
+ "can't omit precision for a %"PRIsVALUE".",
+ RB_OBJ_CLASSNAME(iniValue));
}
return ToValue(GetVpValueWithPrec(iniValue, mf, 1));
@@ -2554,7 +2565,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
else if (vx == NULL) {
cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
}
- RB_GC_GUARD(vx->obj);
+ x = RB_GC_GUARD(vx->obj);
n = prec + rmpd_double_figures();
negative = VpGetSign(vx) < 0;
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index 4048d1345d..3b15ccde29 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -1,5 +1,5 @@
/*
- date_core.c: Coded by Tadayoshi Funaba 2010, 2011
+ date_core.c: Coded by Tadayoshi Funaba 2010-2013
*/
#include "ruby.h"
@@ -991,8 +991,14 @@ safe_mul_p(VALUE x, long m)
if (!FIXNUM_P(x))
return 0;
ix = FIX2LONG(x);
- if (ix >= (FIXNUM_MAX / m))
- return 0;
+ if (ix < 0) {
+ if (ix <= (FIXNUM_MIN / m))
+ return 0;
+ }
+ else {
+ if (ix >= (FIXNUM_MAX / m))
+ return 0;
+ }
return 1;
}
@@ -1109,6 +1115,28 @@ m_virtual_sg(union DateData *x)
return c_virtual_sg(x);
}
+#define canonicalize_jd(_nth, _jd) \
+{\
+ if (_jd < 0) {\
+ _nth = f_sub(_nth, INT2FIX(1));\
+ _jd += CM_PERIOD;\
+ }\
+ if (_jd >= CM_PERIOD) {\
+ _nth = f_add(_nth, INT2FIX(1));\
+ _jd -= CM_PERIOD;\
+ }\
+}
+
+inline static void
+canonicalize_s_jd(union DateData *x)
+{
+ int j = x->s.jd;
+ assert(have_jd_p(x));
+ canonicalize_jd(x->s.nth, x->s.jd);
+ if (x->s.jd != j)
+ x->flags &= ~HAVE_CIVIL;
+}
+
inline static void
get_s_jd(union DateData *x)
{
@@ -1194,6 +1222,16 @@ get_c_time(union DateData *x)
}
inline static void
+canonicalize_c_jd(union DateData *x)
+{
+ int j = x->c.jd;
+ assert(have_jd_p(x));
+ canonicalize_jd(x->c.nth, x->c.jd);
+ if (x->c.jd != j)
+ x->flags &= ~HAVE_CIVIL;
+}
+
+inline static void
get_c_jd(union DateData *x)
{
assert(complex_dat_p(x));
@@ -1366,6 +1404,19 @@ guess_style(VALUE y, double sg) /* -/+oo or zero */
return style;
}
+inline static void
+m_canonicalize_jd(union DateData *x)
+{
+ if (simple_dat_p(x)) {
+ get_s_jd(x);
+ canonicalize_s_jd(x);
+ }
+ else {
+ get_c_jd(x);
+ canonicalize_c_jd(x);
+ }
+}
+
inline static VALUE
m_nth(union DateData *x)
{
@@ -1972,7 +2023,7 @@ civil_to_jd(VALUE y, int m, int d, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2007,7 +2058,7 @@ ordinal_to_jd(VALUE y, int d, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2042,7 +2093,7 @@ commercial_to_jd(VALUE y, int w, int d, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2077,7 +2128,7 @@ weeknum_to_jd(VALUE y, int w, int d, int f, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2112,7 +2163,7 @@ nth_kday_to_jd(VALUE y, int m, int n, int k, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2151,7 +2202,7 @@ valid_ordinal_p(VALUE y, int d, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2190,7 +2241,7 @@ valid_civil_p(VALUE y, int m, int d, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2226,7 +2277,7 @@ valid_commercial_p(VALUE y, int w, int d, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2256,7 +2307,7 @@ valid_weeknum_p(VALUE y, int w, int d, int f, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -2287,7 +2338,7 @@ valid_nth_kday_p(VALUE y, int m, int n, int k, double sg,
*ry = FIX2INT(y);
else {
VALUE nth2;
- decode_year(y, ns ? -1 : +1, &nth2, ry);
+ decode_year(y, *ns ? -1 : +1, &nth2, ry);
}
}
else {
@@ -5569,15 +5620,7 @@ d_lite_plus(VALUE self, VALUE other)
jd = m_jd(dat);
else {
jd = m_jd(dat) + (int)t;
-
- if (jd < 0) {
- nth = f_sub(nth, INT2FIX(1));
- jd += CM_PERIOD;
- }
- else if (jd >= CM_PERIOD) {
- nth = f_add(nth, INT2FIX(1));
- jd -= CM_PERIOD;
- }
+ canonicalize_jd(nth, jd);
}
if (simple_dat_p(dat))
@@ -5630,14 +5673,7 @@ d_lite_plus(VALUE self, VALUE other)
jd = m_jd(dat);
else {
jd = m_jd(dat) + jd;
- if (jd < 0) {
- nth = f_sub(nth, INT2FIX(1));
- jd += CM_PERIOD;
- }
- else if (jd >= CM_PERIOD) {
- nth = f_add(nth, INT2FIX(1));
- jd -= CM_PERIOD;
- }
+ canonicalize_jd(nth, jd);
}
if (f_zero_p(nth))
@@ -5744,14 +5780,7 @@ d_lite_plus(VALUE self, VALUE other)
jd = m_jd(dat);
else {
jd = m_jd(dat) + jd;
- if (jd < 0) {
- nth = f_sub(nth, INT2FIX(1));
- jd += CM_PERIOD;
- }
- else if (jd >= CM_PERIOD) {
- nth = f_add(nth, INT2FIX(1));
- jd -= CM_PERIOD;
- }
+ canonicalize_jd(nth, jd);
}
if (f_zero_p(nth))
@@ -5854,14 +5883,7 @@ d_lite_plus(VALUE self, VALUE other)
jd = m_jd(dat);
else {
jd = m_jd(dat) + jd;
- if (jd < 0) {
- nth = f_sub(nth, INT2FIX(1));
- jd += CM_PERIOD;
- }
- else if (jd >= CM_PERIOD) {
- nth = f_add(nth, INT2FIX(1));
- jd -= CM_PERIOD;
- }
+ canonicalize_jd(nth, jd);
}
if (f_zero_p(nth))
@@ -5905,15 +5927,7 @@ minus_dd(VALUE self, VALUE other)
d = m_jd(adat) - m_jd(bdat);
df = m_df(adat) - m_df(bdat);
sf = f_sub(m_sf(adat), m_sf(bdat));
-
- if (d < 0) {
- n = f_sub(n, INT2FIX(1));
- d += CM_PERIOD;
- }
- else if (d >= CM_PERIOD) {
- n = f_add(n, INT2FIX(1));
- d -= CM_PERIOD;
- }
+ canonicalize_jd(n, d);
if (df < 0) {
d -= 1;
@@ -6299,6 +6313,8 @@ cmp_dd(VALUE self, VALUE other)
int a_jd, b_jd,
a_df, b_df;
+ m_canonicalize_jd(adat);
+ m_canonicalize_jd(bdat);
a_nth = m_nth(adat);
b_nth = m_nth(bdat);
if (f_eqeq_p(a_nth, b_nth)) {
@@ -6379,6 +6395,8 @@ d_lite_cmp(VALUE self, VALUE other)
VALUE a_nth, b_nth;
int a_jd, b_jd;
+ m_canonicalize_jd(adat);
+ m_canonicalize_jd(bdat);
a_nth = m_nth(adat);
b_nth = m_nth(bdat);
if (f_eqeq_p(a_nth, b_nth)) {
@@ -6413,6 +6431,8 @@ d_lite_cmp(VALUE self, VALUE other)
a_pd, b_pd;
#endif
+ m_canonicalize_jd(adat);
+ m_canonicalize_jd(bdat);
a_nth = m_nth(adat);
b_nth = m_nth(bdat);
if (f_eqeq_p(a_nth, b_nth)) {
@@ -6520,6 +6540,8 @@ d_lite_equal(VALUE self, VALUE other)
VALUE a_nth, b_nth;
int a_jd, b_jd;
+ m_canonicalize_jd(adat);
+ m_canonicalize_jd(bdat);
a_nth = m_nth(adat);
b_nth = m_nth(bdat);
a_jd = m_local_jd(adat);
@@ -6541,6 +6563,8 @@ d_lite_equal(VALUE self, VALUE other)
a_pd, b_pd;
#endif
+ m_canonicalize_jd(adat);
+ m_canonicalize_jd(bdat);
a_nth = m_nth(adat);
b_nth = m_nth(bdat);
if (f_eqeq_p(a_nth, b_nth)) {
@@ -7006,7 +7030,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
*
* Seconds since the Unix Epoch:
* %s - Number of seconds since 1970-01-01 00:00:00 UTC.
- * %Q - Number of microseconds since 1970-01-01 00:00:00 UTC.
+ * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
*
* Literal string:
* %n - Newline character (\n)
@@ -8441,7 +8465,7 @@ dt_lite_to_s(VALUE self)
*
* Seconds since the Unix Epoch:
* %s - Number of seconds since 1970-01-01 00:00:00 UTC.
- * %Q - Number of microseconds since 1970-01-01 00:00:00 UTC.
+ * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
*
* Literal string:
* %n - Newline character (\n)
diff --git a/ext/date/date_parse.c b/ext/date/date_parse.c
index 903163003c..0ce0663804 100644
--- a/ext/date/date_parse.c
+++ b/ext/date/date_parse.c
@@ -701,9 +701,9 @@ parse_time(VALUE str, VALUE hash)
"("
"(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
"|"
- "[[:alpha:].\\s]+(?:standard|daylight)\\stime\\b"
+ "(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\stime\\b"
"|"
- "[[:alpha:]]+(?:\\sdst)?\\b"
+ "(?-i:[[:alpha:]]+)(?:\\sdst)?\\b"
")"
")?";
static VALUE pat = Qnil;
@@ -2147,7 +2147,9 @@ rfc2822_cb(VALUE m, VALUE hash)
s[i] = rb_reg_nth_match(i, m);
}
- set_hash("wday", INT2FIX(day_num(s[1])));
+ if (!NIL_P(s[1])) {
+ set_hash("wday", INT2FIX(day_num(s[1])));
+ }
set_hash("mday", str2num(s[2]));
set_hash("mon", INT2FIX(mon_num(s[3])));
y = str2num(s[4]);
diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c
index eaec8e716b..f1196bc0bd 100644
--- a/ext/date/date_strptime.c
+++ b/ext/date/date_strptime.c
@@ -566,8 +566,8 @@ date__strptime_internal(const char *str, size_t slen,
static const char pat_source[] =
"\\A("
"(?:gmt|utc?)?[-+]\\d+(?:[,.:]\\d+(?::\\d+)?)?"
- "|[[:alpha:].\\s]+(?:standard|daylight)\\s+time\\b"
- "|[[:alpha:]]+(?:\\s+dst)?\\b"
+ "|(?-i:[[:alpha:].\\s]+)(?:standard|daylight)\\s+time\\b"
+ "|(?-i:[[:alpha:]]+)(?:\\s+dst)?\\b"
")";
static VALUE pat = Qnil;
VALUE m, b;
diff --git a/ext/dl/cptr.c b/ext/dl/cptr.c
index 89dcb942c0..e60fbb48da 100644
--- a/ext/dl/cptr.c
+++ b/ext/dl/cptr.c
@@ -7,6 +7,15 @@
#include <ctype.h>
#include "dl.h"
+#ifdef PRIsVALUE
+# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
+# define RB_OBJ_STRING(obj) (obj)
+#else
+# define PRIsVALUE "s"
+# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
+# define RB_OBJ_STRING(obj) StringValueCStr(obj)
+#endif
+
VALUE rb_cDLCPtr;
static inline freefunc_t
@@ -400,12 +409,10 @@ static VALUE
rb_dlptr_inspect(VALUE self)
{
struct ptr_data *data;
- char str[1024];
TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- snprintf(str, 1023, "#<%s:%p ptr=%p size=%ld free=%p>",
- rb_class2name(CLASS_OF(self)), data, data->ptr, data->size, data->free);
- return rb_str_new2(str);
+ return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>",
+ RB_OBJ_CLASSNAME(self), data, data->ptr, data->size, data->free);
}
/*
diff --git a/ext/dl/lib/dl/func.rb b/ext/dl/lib/dl/func.rb
index 7b9b54f318..9a984ed2b7 100644
--- a/ext/dl/lib/dl/func.rb
+++ b/ext/dl/lib/dl/func.rb
@@ -92,6 +92,9 @@ module DL
super
else
funcs = []
+ if $SAFE >= 1 && args.any? { |x| x.tainted? }
+ raise SecurityError, "tainted parameter not allowed"
+ end
_args = wrap_args(args, @stack.types, funcs, &block)
r = @cfunc.call(@stack.pack(_args))
funcs.each{|f| f.unbind_at_call()}
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c
index 21796660c4..a1413206fd 100644
--- a/ext/fiddle/closure.c
+++ b/ext/fiddle/closure.c
@@ -21,7 +21,7 @@ dealloc(void * ptr)
#ifndef DONT_USE_FFI_CLOSURE_ALLOC
ffi_closure_free(cls->pcl);
#else
- munmap(cls->pcl, sizeof(cls->pcl));
+ munmap(cls->pcl, sizeof(*cls->pcl));
#endif
if (cls->argv) xfree(cls->argv);
xfree(cls);
@@ -228,7 +228,10 @@ initialize(int rbargc, VALUE argv[], VALUE self)
#else
result = ffi_prep_closure(pcl, cif, callback, (void *)self);
cl->code = (void *)pcl;
- mprotect(pcl, sizeof(pcl), PROT_READ | PROT_EXEC);
+ i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC);
+ if (i) {
+ rb_sys_fail("mprotect");
+ }
#endif
if (FFI_OK != result)
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
index ada37a4942..52f7695eb7 100644
--- a/ext/fiddle/function.c
+++ b/ext/fiddle/function.c
@@ -101,6 +101,15 @@ function_call(int argc, VALUE argv[], VALUE self)
TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
+ if (rb_safe_level() >= 1) {
+ for (i = 0; i < argc; i++) {
+ VALUE src = argv[i];
+ if (OBJ_TAINTED(src)) {
+ rb_raise(rb_eSecurityError, "tainted parameter not allowed");
+ }
+ }
+ }
+
values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *));
generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic));
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index efad30c1ca..e0799a01c0 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -684,7 +684,7 @@ console_dev(VALUE klass)
int fd;
#ifdef CONSOLE_DEVICE_FOR_WRITING
- fd = open(CONSOLE_DEVICE_FOR_WRITING, O_WRONLY);
+ fd = open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR);
if (fd < 0) return Qnil;
rb_update_max_fd(fd);
args[1] = INT2FIX(O_WRONLY);
diff --git a/ext/json/generator/depend b/ext/json/generator/depend
index bb76ad6400..563fa435d5 100644
--- a/ext/json/generator/depend
+++ b/ext/json/generator/depend
@@ -1 +1,2 @@
+$(OBJS): $(ruby_headers)
generator.o: generator.c generator.h
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 9ad037cd40..c5bbec08a4 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -5,6 +5,15 @@ static VALUE CEncoding_UTF_8;
static ID i_encoding, i_encode;
#endif
+#ifdef PRIsVALUE
+# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
+# define RB_OBJ_STRING(obj) (obj)
+#else
+# define PRIsVALUE "s"
+# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
+# define RB_OBJ_STRING(obj) StringValueCStr(obj)
+#endif
+
static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
mHash, mArray, mFixnum, mBignum, mFloat, mString, mString_Extend,
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
@@ -876,10 +885,10 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
if (!allow_nan) {
if (isinf(value)) {
fbuffer_free(buffer);
- rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
+ rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
} else if (isnan(value)) {
fbuffer_free(buffer);
- rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
+ rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
}
}
fbuffer_append_str(buffer, tmp);
@@ -1024,6 +1033,7 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
{
JSON_Generator_State *objState, *origState;
+ if (obj == orig) return obj;
Data_Get_Struct(obj, JSON_Generator_State, objState);
Data_Get_Struct(orig, JSON_Generator_State, origState);
if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
diff --git a/ext/json/parser/depend b/ext/json/parser/depend
index 5eaf6dd040..c0d4fc834f 100644
--- a/ext/json/parser/depend
+++ b/ext/json/parser/depend
@@ -1 +1,2 @@
+$(OBJS): $(ruby_headers)
parser.o: parser.c parser.h
diff --git a/ext/openssl/lib/openssl/ssl-internal.rb b/ext/openssl/lib/openssl/ssl-internal.rb
index c70b5b8f6b..a2bb36c2cb 100644
--- a/ext/openssl/lib/openssl/ssl-internal.rb
+++ b/ext/openssl/lib/openssl/ssl-internal.rb
@@ -88,14 +88,22 @@ module OpenSSL
should_verify_common_name = true
cert.extensions.each{|ext|
next if ext.oid != "subjectAltName"
- ext.value.split(/,\s+/).each{|general_name|
- if /\ADNS:(.*)/ =~ general_name
+ ostr = OpenSSL::ASN1.decode(ext.to_der).value.last
+ sequence = OpenSSL::ASN1.decode(ostr.value)
+ sequence.value.each{|san|
+ case san.tag
+ when 2 # dNSName in GeneralName (RFC5280)
should_verify_common_name = false
- reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
+ reg = Regexp.escape(san.value).gsub(/\\\*/, "[^.]+")
return true if /\A#{reg}\z/i =~ hostname
- elsif /\AIP Address:(.*)/ =~ general_name
+ when 7 # iPAddress in GeneralName (RFC5280)
should_verify_common_name = false
- return true if $1 == hostname
+ # follows GENERAL_NAME_print() in x509v3/v3_alt.c
+ if san.value.size == 4
+ return true if san.value.unpack('C*').join('.') == hostname
+ elsif san.value.size == 16
+ return true if san.value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
+ end
end
}
}
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index f3410b64e8..d0c9004a62 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -284,10 +284,9 @@ ossl_to_der_if_possible(VALUE obj)
static VALUE
ossl_make_error(VALUE exc, const char *fmt, va_list args)
{
- char buf[BUFSIZ];
+ VALUE str = Qnil;
const char *msg;
long e;
- int len = 0;
#ifdef HAVE_ERR_PEEK_LAST_ERROR
e = ERR_peek_last_error();
@@ -295,14 +294,20 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args)
e = ERR_peek_error();
#endif
if (fmt) {
- len = vsnprintf(buf, BUFSIZ, fmt, args);
+ str = rb_vsprintf(fmt, args);
}
- if (len < BUFSIZ && e) {
+ if (e) {
if (dOSSL == Qtrue) /* FULL INFO */
msg = ERR_error_string(e, NULL);
else
msg = ERR_reason_error_string(e);
- len += snprintf(buf+len, BUFSIZ-len, "%s%s", (len ? ": " : ""), msg);
+ if (NIL_P(str)) {
+ if (msg) str = rb_str_new_cstr(msg);
+ }
+ else {
+ if (RSTRING_LEN(str)) rb_str_cat2(str, ": ");
+ rb_str_cat2(str, msg ? msg : "(null)");
+ }
}
if (dOSSL == Qtrue){ /* show all errors on the stack */
while ((e = ERR_get_error()) != 0){
@@ -311,8 +316,8 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args)
}
ERR_clear_error();
- if(len > BUFSIZ) len = rb_long2int(strlen(buf));
- return rb_exc_new(exc, buf, len);
+ if (NIL_P(str)) str = rb_str_new(0, 0);
+ return rb_exc_new3(exc, str);
}
void
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 97095f7d6f..31d0509e1d 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -89,15 +89,15 @@ extern VALUE eOSSLError;
*/
#define OSSL_Check_Kind(obj, klass) do {\
if (!rb_obj_is_kind_of((obj), (klass))) {\
- ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected kind of %s)",\
- rb_obj_classname(obj), rb_class2name(klass));\
+ ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected kind of %s)",\
+ RB_OBJ_CLASSNAME(obj), rb_class2name(klass));\
}\
} while (0)
#define OSSL_Check_Instance(obj, klass) do {\
if (!rb_obj_is_instance_of((obj), (klass))) {\
- ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected instance of %s)",\
- rb_obj_classname(obj), rb_class2name(klass));\
+ ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected instance of %s)",\
+ RB_OBJ_CLASSNAME(obj), rb_class2name(klass));\
}\
} while (0)
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 210ae5ca8b..ae5e476b5f 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -33,15 +33,22 @@ asn1time_to_time(ASN1_TIME *time)
{
struct tm tm;
VALUE argv[6];
+ int count;
if (!time || !time->data) return Qnil;
memset(&tm, 0, sizeof(struct tm));
switch (time->type) {
case V_ASN1_UTCTIME:
- if (sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
- &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- ossl_raise(rb_eTypeError, "bad UTCTIME format");
+ count = sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
+ &tm.tm_sec);
+
+ if (count == 5) {
+ tm.tm_sec = 0;
+ } else if (count != 6) {
+ ossl_raise(rb_eTypeError, "bad UTCTIME format: \"%s\"",
+ time->data);
}
if (tm.tm_year < 69) {
tm.tm_year += 2000;
@@ -617,8 +624,8 @@ ossl_asn1_default_tag(VALUE obj)
}
tmp_class = rb_class_superclass(tmp_class);
}
- ossl_raise(eASN1Error, "universal tag for %s not found",
- rb_class2name(CLASS_OF(obj)));
+ ossl_raise(eASN1Error, "universal tag for %"PRIsVALUE" not found",
+ RB_OBJ_CLASSNAME(obj));
return -1; /* dummy */
}
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 26851515cd..c046518b0e 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -213,10 +213,10 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
* We deprecated the arguments for this method, but we decided
* keeping this behaviour for backward compatibility.
*/
- const char *cname = rb_class2name(rb_obj_class(self));
- rb_warn("arguments for %s#encrypt and %s#decrypt were deprecated; "
- "use %s#pkcs5_keyivgen to derive key and IV",
- cname, cname, cname);
+ VALUE cname = rb_class_path(rb_obj_class(self));
+ rb_warn("arguments for %"PRIsVALUE"#encrypt and %"PRIsVALUE"#decrypt were deprecated; "
+ "use %"PRIsVALUE"#pkcs5_keyivgen to derive key and IV",
+ RB_OBJ_STRING(cname), RB_OBJ_STRING(cname), RB_OBJ_STRING(cname));
StringValue(pass);
GetCipher(self, ctx);
if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index a7d1e315fd..51cfb088be 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -347,18 +347,11 @@ ossl_engine_get_cmds(VALUE self)
static VALUE
ossl_engine_inspect(VALUE self)
{
- VALUE str;
- const char *cname = rb_class2name(rb_obj_class(self));
-
- str = rb_str_new2("#<");
- rb_str_cat2(str, cname);
- rb_str_cat2(str, " id=\"");
- rb_str_append(str, ossl_engine_get_id(self));
- rb_str_cat2(str, "\" name=\"");
- rb_str_append(str, ossl_engine_get_name(self));
- rb_str_cat2(str, "\">");
-
- return str;
+ ENGINE *e;
+
+ GetEngine(self, e);
+ return rb_sprintf("#<%"PRIsVALUE" id=\"%s\" name=\"%s\">",
+ RB_OBJ_CLASSNAME(self), ENGINE_get_id(e), ENGINE_get_name(e));
}
#define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 748d9c82fd..0a0c170c42 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -572,7 +572,7 @@ Init_ossl_dh()
*
* === Example of a key exchange
* dh1 = OpenSSL::PKey::DH.new(2048)
- * params = dh1.public_key.to_der #you may send this publicly to the participating party
+ * der = dh1.public_key.to_der #you may send this publicly to the participating party
* dh2 = OpenSSL::PKey::DH.new(der)
* dh2.generate_key! #generate the per-session key pair
* symm_key1 = dh1.compute_key(dh2.pub_key)
@@ -615,4 +615,3 @@ Init_ossl_dh()
{
}
#endif /* NO_DH */
-
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index 9f1050f62d..dd491ef263 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -757,8 +757,10 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
method = EC_GFp_mont_method();
} else if (id == s_GFp_nist) {
method = EC_GFp_nist_method();
+#if !defined(OPENSSL_NO_EC2M)
} else if (id == s_GF2m_simple) {
method = EC_GF2m_simple_method();
+#endif
}
if (method) {
@@ -812,8 +814,10 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
if (id == s_GFp) {
new_curve = EC_GROUP_new_curve_GFp;
+#if !defined(OPENSSL_NO_EC2M)
} else if (id == s_GF2m) {
new_curve = EC_GROUP_new_curve_GF2m;
+#endif
} else {
ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
}
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 2b52bf07c3..e437e7ecd6 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -995,7 +995,6 @@ ossl_ssl_shutdown(SSL *ssl)
static void
ossl_ssl_free(SSL *ssl)
{
- ossl_ssl_shutdown(ssl);
SSL_free(ssl);
}
@@ -1405,9 +1404,16 @@ ossl_ssl_close(VALUE self)
SSL *ssl;
Data_Get_Struct(self, SSL, ssl);
- ossl_ssl_shutdown(ssl);
- if (RTEST(ossl_ssl_get_sync_close(self)))
- rb_funcall(ossl_ssl_get_io(self), rb_intern("close"), 0);
+ if (ssl) {
+ VALUE io = ossl_ssl_get_io(self);
+ if (!RTEST(rb_funcall(io, rb_intern("closed?"), 0))) {
+ ossl_ssl_shutdown(ssl);
+ SSL_free(ssl);
+ DATA_PTR(self) = NULL;
+ if (RTEST(ossl_ssl_get_sync_close(self)))
+ rb_funcall(io, rb_intern("close"), 0);
+ }
+ }
return Qnil;
}
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index f5b2f4ff4a..80a0b76206 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -692,35 +692,20 @@ ossl_x509_add_extension(VALUE self, VALUE extension)
static VALUE
ossl_x509_inspect(VALUE self)
{
- VALUE str;
- const char *cname = rb_class2name(rb_obj_class(self));
-
- str = rb_str_new2("#<");
- rb_str_cat2(str, cname);
- rb_str_cat2(str, " ");
-
- rb_str_cat2(str, "subject=");
- rb_str_append(str, rb_inspect(ossl_x509_get_subject(self)));
- rb_str_cat2(str, ", ");
-
- rb_str_cat2(str, "issuer=");
- rb_str_append(str, rb_inspect(ossl_x509_get_issuer(self)));
- rb_str_cat2(str, ", ");
-
- rb_str_cat2(str, "serial=");
- rb_str_append(str, rb_inspect(ossl_x509_get_serial(self)));
- rb_str_cat2(str, ", ");
-
- rb_str_cat2(str, "not_before=");
- rb_str_append(str, rb_inspect(ossl_x509_get_not_before(self)));
- rb_str_cat2(str, ", ");
-
- rb_str_cat2(str, "not_after=");
- rb_str_append(str, rb_inspect(ossl_x509_get_not_after(self)));
-
- str = rb_str_cat2(str, ">");
-
- return str;
+ VALUE subject = rb_inspect(ossl_x509_get_subject(self));
+ VALUE issuer = rb_inspect(ossl_x509_get_issuer(self));
+ VALUE serial = rb_inspect(ossl_x509_get_serial(self));
+ VALUE not_before = rb_inspect(ossl_x509_get_not_before(self));
+ VALUE not_after = rb_inspect(ossl_x509_get_not_after(self));
+ return rb_sprintf("#<%"PRIsVALUE": subject=%"PRIsVALUE", "
+ "issuer=%"PRIsVALUE", serial=%"PRIsVALUE", "
+ "not_before=%"PRIsVALUE", not_after=%"PRIsVALUE">",
+ RB_OBJ_CLASSNAME(self),
+ RB_OBJ_STRING(subject),
+ RB_OBJ_STRING(issuer),
+ RB_OBJ_STRING(serial),
+ RB_OBJ_STRING(not_before),
+ RB_OBJ_STRING(not_after));
}
/*
diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h
index 1c5d05baca..9a537bb914 100644
--- a/ext/openssl/ruby_missing.h
+++ b/ext/openssl/ruby_missing.h
@@ -38,4 +38,13 @@
#define rb_block_call(arg1, arg2, arg3, arg4, arg5, arg6) rb_iterate(rb_each, (arg1), (arg5), (arg6))
#endif /* ! HAVE_RB_BLOCK_CALL */
+#ifdef PRIsVALUE
+# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
+# define RB_OBJ_STRING(obj) (obj)
+#else
+# define PRIsVALUE "s"
+# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
+# define RB_OBJ_STRING(obj) StringValueCStr(obj)
+#endif
+
#endif /* _OSSL_RUBY_MISSING_H_ */
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index b18eb68f77..8eaf73a624 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -609,7 +609,7 @@ static void
raise_from_check(pid_t pid, int status)
{
const char *state;
- char buf[1024];
+ VALUE msg;
VALUE exc;
#if defined(WIFSTOPPED)
@@ -627,8 +627,8 @@ raise_from_check(pid_t pid, int status)
else {
state = "exited";
}
- snprintf(buf, sizeof(buf), "pty - %s: %ld", state, (long)pid);
- exc = rb_exc_new2(eChildExited, buf);
+ msg = rb_sprintf("pty - %s: %ld", state, (long)pid);
+ exc = rb_exc_new3(eChildExited, msg);
rb_iv_set(exc, "status", rb_last_status_get());
rb_exc_raise(exc);
}
diff --git a/ext/ripper/lib/ripper/lexer.rb b/ext/ripper/lib/ripper/lexer.rb
index 5bbee39e06..ac4dcafd65 100644
--- a/ext/ripper/lib/ripper/lexer.rb
+++ b/ext/ripper/lib/ripper/lexer.rb
@@ -12,13 +12,17 @@ require 'ripper/core'
class Ripper
- # Tokenizes Ruby program and returns an Array of String.
+ # Tokenizes the Ruby program and returns an array of strings.
+ #
+ # p Ripper.tokenize("def m(a) nil end")
+ # # => ["def", " ", "m", "(", "a", ")", " ", "nil", " ", "end"]
+ #
def Ripper.tokenize(src, filename = '-', lineno = 1)
Lexer.new(src, filename, lineno).tokenize
end
- # Tokenizes Ruby program and returns an Array of Array,
- # which is formatted like [[lineno, column], type, token].
+ # Tokenizes the Ruby program and returns an array of an array,
+ # which is formatted like <code>[[lineno, column], type, token]</code>.
#
# require 'ripper'
# require 'pp'
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index c01a1c272a..304565eec8 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -1277,12 +1277,11 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
ss = rb_sendmsg(fptr->fd, &mh, flags);
- if (!nonblock && rb_io_wait_writable(fptr->fd)) {
- rb_io_check_closed(fptr);
- goto retry;
- }
-
if (ss == -1) {
+ if (!nonblock && rb_io_wait_writable(fptr->fd)) {
+ rb_io_check_closed(fptr);
+ goto retry;
+ }
if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
rb_mod_sys_fail(rb_mWaitWritable, "sendmsg(2) would block");
rb_sys_fail("sendmsg(2)");
@@ -1575,12 +1574,11 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
ss = rb_recvmsg(fptr->fd, &mh, flags);
- if (!nonblock && rb_io_wait_readable(fptr->fd)) {
- rb_io_check_closed(fptr);
- goto retry;
- }
-
if (ss == -1) {
+ if (!nonblock && rb_io_wait_readable(fptr->fd)) {
+ rb_io_check_closed(fptr);
+ goto retry;
+ }
if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
rb_mod_sys_fail(rb_mWaitReadable, "recvmsg(2) would block");
#if defined(HAVE_ST_MSG_CONTROL)
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 380b3ecde0..5c29876a4b 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -24,6 +24,12 @@ else
have_library("socket", "socket")
end
+if /darwin/ =~ RUBY_PLATFORM
+ # For IPv6 extension header access on OS X 10.7+ [Bug #8517]
+ $CFLAGS << " -D__APPLE_USE_RFC_3542"
+end
+
+headers = []
unless $mswin or $bccwin or $mingw
headers = %w<sys/types.h netdb.h string.h sys/socket.h netinet/in.h>
end
diff --git a/ext/socket/init.c b/ext/socket/init.c
index 54452e4b99..e63fb80c74 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -281,8 +281,12 @@ wait_connectable(int fd)
*/
if (ret < 0)
break;
- if (sockerr == 0)
- continue; /* workaround for winsock */
+ if (sockerr == 0) {
+ if (revents & RB_WAITFD_OUT)
+ break;
+ else
+ continue; /* workaround for winsock */
+ }
/* BSD and Linux use sockerr. */
errno = sockerr;
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index 66ff548270..ee6e9eabe1 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -41,13 +41,18 @@ class Addrinfo
sock.ipv6only! if self.ipv6?
sock.bind local_addrinfo if local_addrinfo
sock.connect(self)
- if block_given?
+ rescue Exception
+ sock.close
+ raise
+ end
+ if block_given?
+ begin
yield sock
- else
- sock
+ ensure
+ sock.close if !sock.closed?
end
- ensure
- sock.close if !sock.closed? && (block_given? || $!)
+ else
+ sock
end
end
private :connect_internal
@@ -123,13 +128,18 @@ class Addrinfo
sock.ipv6only! if self.ipv6?
sock.setsockopt(:SOCKET, :REUSEADDR, 1)
sock.bind(self)
- if block_given?
+ rescue Exception
+ sock.close
+ raise
+ end
+ if block_given?
+ begin
yield sock
- else
- sock
+ ensure
+ sock.close if !sock.closed?
end
- ensure
- sock.close if !sock.closed? && (block_given? || $!)
+ else
+ sock
end
end
@@ -141,13 +151,18 @@ class Addrinfo
sock.setsockopt(:SOCKET, :REUSEADDR, 1)
sock.bind(self)
sock.listen(backlog)
- if block_given?
+ rescue Exception
+ sock.close
+ raise
+ end
+ if block_given?
+ begin
yield sock
- else
- sock
+ ensure
+ sock.close if !sock.closed?
end
- ensure
- sock.close if !sock.closed? && (block_given? || $!)
+ else
+ sock
end
end
@@ -278,8 +293,9 @@ class Socket < BasicSocket
# :stopdoc:
def self.ip_sockets_port0(ai_list, reuseaddr)
+ sockets = []
begin
- sockets = []
+ sockets.clear
port = nil
ai_list.each {|ai|
begin
@@ -300,14 +316,13 @@ class Socket < BasicSocket
end
}
rescue Errno::EADDRINUSE
- sockets.each {|s|
- s.close
- }
+ sockets.each {|s| s.close }
retry
+ rescue Exception
+ sockets.each {|s| s.close }
+ raise
end
sockets
- ensure
- sockets.each {|s| s.close if !s.closed? } if $!
end
class << self
private :ip_sockets_port0
@@ -316,12 +331,15 @@ class Socket < BasicSocket
def self.tcp_server_sockets_port0(host)
ai_list = Addrinfo.getaddrinfo(host, 0, nil, :STREAM, nil, Socket::AI_PASSIVE)
sockets = ip_sockets_port0(ai_list, true)
- sockets.each {|s|
- s.listen(5)
- }
+ begin
+ sockets.each {|s|
+ s.listen(5)
+ }
+ rescue Exception
+ sockets.each {|s| s.close }
+ raise
+ end
sockets
- ensure
- sockets.each {|s| s.close if !s.closed? } if $! && sockets
end
class << self
private :tcp_server_sockets_port0
@@ -365,9 +383,9 @@ class Socket < BasicSocket
if port == 0
sockets = tcp_server_sockets_port0(host)
else
+ last_error = nil
+ sockets = []
begin
- last_error = nil
- sockets = []
Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai|
begin
s = ai.listen
@@ -380,8 +398,9 @@ class Socket < BasicSocket
if sockets.empty?
raise last_error
end
- ensure
- sockets.each {|s| s.close if !s.closed? } if $!
+ rescue Exception
+ sockets.each {|s| s.close }
+ raise
end
end
if block_given?
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c
index 80e59a073f..fc2f63a9b3 100644
--- a/ext/socket/raddrinfo.c
+++ b/ext/socket/raddrinfo.c
@@ -157,9 +157,17 @@ struct getaddrinfo_arg
static VALUE
nogvl_getaddrinfo(void *arg)
{
+ int ret;
struct getaddrinfo_arg *ptr = arg;
- return getaddrinfo(ptr->node, ptr->service,
- ptr->hints, ptr->res);
+ ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res);
+#ifdef __linux__
+ /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
+ * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
+ */
+ if (ret == EAI_SYSTEM && errno == ENOENT)
+ ret = EAI_NONAME;
+#endif
+ return (VALUE)ret;
}
#endif
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c
index dcad837a37..2a5bf4f7c8 100644
--- a/ext/strscan/strscan.c
+++ b/ext/strscan/strscan.c
@@ -14,6 +14,15 @@
#define STRSCAN_VERSION "0.7.0"
+#ifdef PRIsVALUE
+# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
+# define RB_OBJ_STRING(obj) (obj)
+#else
+# define PRIsVALUE "s"
+# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
+# define RB_OBJ_STRING(obj) StringValueCStr(obj)
+#endif
+
/* =======================================================================
Data Type Definitions
======================================================================= */
@@ -1063,37 +1072,32 @@ static VALUE
strscan_inspect(VALUE self)
{
struct strscanner *p;
- char buf[BUFSIZE];
- long len;
VALUE a, b;
Data_Get_Struct(self, struct strscanner, p);
if (NIL_P(p->str)) {
- len = snprintf(buf, BUFSIZE, "#<%s (uninitialized)>",
- rb_class2name(CLASS_OF(self)));
- return infect(rb_str_new(buf, len), p);
+ a = rb_sprintf("#<%"PRIsVALUE" (uninitialized)>", RB_OBJ_CLASSNAME(self));
+ return infect(a, p);
}
if (EOS_P(p)) {
- len = snprintf(buf, BUFSIZE, "#<%s fin>",
- rb_class2name(CLASS_OF(self)));
- return infect(rb_str_new(buf, len), p);
+ a = rb_sprintf("#<%"PRIsVALUE" fin>", RB_OBJ_CLASSNAME(self));
+ return infect(a, p);
}
if (p->curr == 0) {
- b = inspect2(p);
- len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld @ %s>",
- rb_class2name(CLASS_OF(self)),
- p->curr, S_LEN(p),
- RSTRING_PTR(b));
- return infect(rb_str_new(buf, len), p);
+ b = inspect2(p);
+ a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld @ %"PRIsVALUE">",
+ RB_OBJ_CLASSNAME(self),
+ p->curr, S_LEN(p),
+ RB_OBJ_STRING(b));
+ return infect(a, p);
}
a = inspect1(p);
b = inspect2(p);
- len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld %s @ %s>",
- rb_class2name(CLASS_OF(self)),
- p->curr, S_LEN(p),
- RSTRING_PTR(a),
- RSTRING_PTR(b));
- return infect(rb_str_new(buf, len), p);
+ a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld %"PRIsVALUE" @ %"PRIsVALUE">",
+ RB_OBJ_CLASSNAME(self),
+ p->curr, S_LEN(p),
+ RB_OBJ_STRING(a), RB_OBJ_STRING(b));
+ return infect(a, p);
}
static VALUE
@@ -1118,21 +1122,19 @@ inspect1(struct strscanner *p)
static VALUE
inspect2(struct strscanner *p)
{
- char buf[BUFSIZE];
- char *bp = buf;
+ VALUE str;
long len;
if (EOS_P(p)) return rb_str_new2("");
len = S_LEN(p) - p->curr;
if (len > INSPECT_LENGTH) {
- len = INSPECT_LENGTH;
- memcpy(bp, CURPTR(p), len); bp += len;
- strcpy(bp, "..."); bp += 3;
+ str = rb_str_new(CURPTR(p), INSPECT_LENGTH);
+ rb_str_cat2(str, "...");
}
else {
- memcpy(bp, CURPTR(p), len); bp += len;
+ str = rb_str_new(CURPTR(p), len);
}
- return rb_str_dump(rb_str_new(buf, bp - buf));
+ return rb_str_dump(str);
}
/* =======================================================================
diff --git a/ext/syslog/syslog.c b/ext/syslog/syslog.c
index d1f75101e4..28cee3de28 100644
--- a/ext/syslog/syslog.c
+++ b/ext/syslog/syslog.c
@@ -12,6 +12,15 @@
#include "ruby/util.h"
#include <syslog.h>
+#ifdef PRIsVALUE
+# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
+# define RB_OBJ_STRING(obj) (obj)
+#else
+# define PRIsVALUE "s"
+# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
+# define RB_OBJ_STRING(obj) StringValueCStr(obj)
+#endif
+
/* Syslog class */
static VALUE mSyslog, mSyslogConstants;
static const char *syslog_ident = NULL;
@@ -301,7 +310,7 @@ static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self)
pri = *argv++;
if (!FIXNUM_P(pri)) {
- rb_raise(rb_eTypeError, "type mismatch: %s given", rb_class2name(CLASS_OF(pri)));
+ rb_raise(rb_eTypeError, "type mismatch: %"PRIsVALUE" given", RB_OBJ_CLASSNAME(pri));
}
syslog_write(FIX2INT(pri), argc, argv);
@@ -313,24 +322,17 @@ static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self)
*/
static VALUE mSyslog_inspect(VALUE self)
{
- char buf[1024];
-
Check_Type(self, T_MODULE);
- if (syslog_opened) {
- snprintf(buf, sizeof(buf),
- "<#%s: opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>",
- rb_class2name(self),
- syslog_ident,
- syslog_options,
- syslog_facility,
- syslog_mask);
- } else {
- snprintf(buf, sizeof(buf),
- "<#%s: opened=false>", rb_class2name(self));
- }
+ if (!syslog_opened)
+ return rb_sprintf("<#%s: opened=false>", rb_class2name(self));
- return rb_str_new2(buf);
+ return rb_sprintf("<#%s: opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>",
+ rb_class2name(self),
+ syslog_ident,
+ syslog_options,
+ syslog_facility,
+ syslog_mask);
}
/* Returns self, for backward compatibility.
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
index 2f68d01e7f..3f8c50ff6d 100644
--- a/ext/tk/extconf.rb
+++ b/ext/tk/extconf.rb
@@ -8,12 +8,21 @@ TkLib_Config = {}
TkLib_Config['search_versions'] =
# %w[8.9 8.8 8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6 4.2]
# %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0]
- %w[8.7 8.6 8.5 8.4 8.0] # to shorten search steps
+ # %w[8.7 8.6 8.5 8.4 8.0] # to shorten search steps
+ %w[8.5 8.4] # At present, Tcl/Tk8.6 is not supported.
+
+TkLib_Config['unsupported_versions'] =
+ %w[8.8 8.7 8.6] # At present, Tcl/Tk8.6 is not supported.
TkLib_Config['major_nums'] = '87'
##############################################################
+
+TkLib_Config['enable-shared'] = enable_config("shared")
+
+
+##############################################################
# use old extconf.rb ?
##############################################################
if with_config('tk-old-extconf')
@@ -114,7 +123,7 @@ def is_macosx?
end
def maybe_64bit?
- /64|universal/ =~ RUBY_PLATFORM
+ /64|universal|s390x/ =~ RUBY_PLATFORM
end
def check_tcltk_version(version)
@@ -313,7 +322,9 @@ def find_macosx_framework
paths.reverse! unless TkLib_Config["ActiveTcl"] # system has higher priority
paths.map{|dir| dir.strip.chomp('/')}.each{|dir|
+ next unless File.exist?(File.join(dir, "Tcl.framework", "Headers"))
next unless File.directory?(tcldir = File.join(dir, "Tcl.framework"))
+ next unless File.exist?(File.join(dir, "Tk.framework", "Headers"))
next unless File.directory?(tkdir = File.join(dir, "Tk.framework"))
TkLib_Config["tcltk-framework"] = dir
return [tcldir, tkdir]
@@ -540,13 +551,13 @@ end
def get_ext_list()
exts = [CONFIG['DLEXT']]
- exts.concat %w(dll lib) if is_win32?
+ exts.concat %w(dll) if is_win32?
exts.concat %w(bundle dylib) if is_macosx? || /nextstep|openstep|rhapsody/ =~ RUBY_PLATFORM
- if enable_config("shared") == false
- [CONFIG['LIBEXT'], "a"].concat exts
- else
- exts.concat [CONFIG['LIBEXT'], "a"]
+ if TkLib_Config["tcltk-stubs"] || TkLib_Config['enable-shared'] == false
+ exts.unshift "lib" if is_win32?
+ exts.unshift "a"
+ exts.unshift CONFIG['LIBEXT']
end
if is_win32?
@@ -734,6 +745,7 @@ def search_tclConfig(*paths) # libdir list or [tcl-libdir|file, tk-libdir|file]
end
conf = nil
+ progress_flag = false
config_dir.uniq!
config_dir.map{|dir|
@@ -744,7 +756,7 @@ def search_tclConfig(*paths) # libdir list or [tcl-libdir|file, tk-libdir|file]
dir.strip.chomp('/')
end
}.each{|dir|
- print(".") # progress
+ print("."); progress_flag = true # progress
# print("check #{dir} ==>");
if dir.kind_of? Array
tcldir, tkdir = dir
@@ -783,10 +795,36 @@ def search_tclConfig(*paths) # libdir list or [tcl-libdir|file, tk-libdir|file]
# parse tclConfig.sh/tkConfig.sh
tclconf = (tclpath)? parse_tclConfig(tclpath): nil
- next if tclconf && tclver && ((tclver_major && tclver_major != tclconf['TCL_MAJOR_VERSION']) || (tclver_minor && tclver_minor != tclconf['TCL_MINOR_VERSION']))
+ if tclconf
+ if tclver && ((tclver_major && tclver_major != tclconf['TCL_MAJOR_VERSION']) || (tclver_minor && tclver_minor != tclconf['TCL_MINOR_VERSION']))
+ print("\n") if progress_flag
+ puts "Ignore \"#{tclpath}\" (unmatch with configured version)."
+ progress_flag = false
+ next
+ end
+ if TkLib_Config['unsupported_versions'].find{|ver| ver == "#{tclconf['TCL_MAJOR_VERSION']}.#{tclconf['TCL_MINOR_VERSION']}"}
+ print("\n") if progress_flag
+ puts "Ignore \"#{tclpath}\" (unsupported version of Tcl/Tk)."
+ progress_flag = false
+ next
+ end
+ end
tkconf = (tkpath)? parse_tclConfig(tkpath): nil
- next if tkconf && tkver && ((tkver_major && tkver_major != tkconf['TK_MAJOR_VERSION']) || (tkver_minor && tkver_minor != tkconf['TK_MINOR_VERSION']))
+ if tkconf
+ if tkver && ((tkver_major && tkver_major != tkconf['TK_MAJOR_VERSION']) || (tkver_minor && tkver_minor != tkconf['TK_MINOR_VERSION']))
+ print("\n") if progress_flag
+ puts "Ignore \"#{tkpath}\" (unmatch with configured version)."
+ progress_flag = false
+ next
+ end
+ if TkLib_Config['unsupported_versions'].find{|ver| ver == "#{tkconf['TK_MAJOR_VERSION']}.#{tkconf['TK_MINOR_VERSION']}"}
+ print("\n") if progress_flag
+ puts "Ignore \"#{tkpath}\" (unsupported version of Tcl/Tk)."
+ progress_flag = false
+ next
+ end
+ end
# nativethread check
if !TkLib_Config["ruby_with_thread"]
@@ -1289,6 +1327,10 @@ end
def find_tcltk_library(tcllib, tklib, stubs, tclversion, tkversion,
tcl_opt_paths, tk_opt_paths)
st,path,lib,libs,*inc = find_tcl(tcllib, stubs, tclversion, *tcl_opt_paths)
+ if !st && TkLib_Config['enable-shared'] == nil
+ TkLib_Config['enable-shared'] = false
+ st,path,lib,libs,*inc = find_tcl(tcllib, stubs, tclversion, *tcl_opt_paths)
+ end
unless st
puts("Warning:: cannot find Tcl library. tcltklib will not be compiled (tcltklib is disabled on your Ruby. That is, Ruby/Tk will not work). Please check configure options.")
return false
@@ -1301,6 +1343,10 @@ def find_tcltk_library(tcllib, tklib, stubs, tclversion, tkversion,
end
st,path,lib,libs,*inc = find_tk(tklib, stubs, tkversion, *tk_opt_paths)
+ if !st && TkLib_Config['enable-shared'] == nil
+ TkLib_Config['enable-shared'] = false
+ st,path,lib,libs,*inc = find_tk(tklib, stubs, tkversion, *tk_opt_paths)
+ end
unless st
puts("Warning:: cannot find Tk library. tcltklib will not be compiled (tcltklib is disabled on your Ruby. That is, Ruby/Tk will not work). Please check configure options.")
return false
@@ -2029,4 +2075,6 @@ if (TkLib_Config["tcltk-framework"] ||
puts "\nFind Tcl/Tk libraries. Make tcltklib.so which is required by Ruby/Tk."
else
puts "\nCan't find proper Tcl/Tk libraries. So, can't make tcltklib.so which is required by Ruby/Tk."
+ puts "If you have Tcl/Tk libraries on your environment, you may be able to use them with configure options (see ext/tk/README.tcltklib)."
+ puts "At present, Tcl/Tk8.6 is not supported. Although you can try to use Tcl/Tk8.6 with configure options, it will not work correctly. I recommend you to use Tcl/Tk8.5 or 8.4."
end
diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb
index 7d3d71675c..af404213e7 100644
--- a/ext/tk/lib/tk/canvas.rb
+++ b/ext/tk/lib/tk/canvas.rb
@@ -85,11 +85,16 @@ class Tk::Canvas<TkWindow
# create a canvas item without creating a TkcItem object
def create(type, *args)
- type = TkcItem.type2class(type.to_s) unless type.kind_of?(TkcItem)
+ if type.kind_of?(Class) && type < TkcItem
+ # do nothing
+ elsif TkcItem.type2class(type.to_s)
+ type = TkcItem.type2class(type.to_s)
+ else
+ fail ArgumentError, "type must a subclass of TkcItem class, or a string in CItemTypeToClass"
+ end
type.create(self, *args)
end
-
def addtag(tag, mode, *args)
mode = mode.to_s
if args[0] && mode =~ /^(above|below|with(tag)?)$/
diff --git a/ext/tk/lib/tk/msgcat.rb b/ext/tk/lib/tk/msgcat.rb
index 4abbcad85e..f2d0653c69 100644
--- a/ext/tk/lib/tk/msgcat.rb
+++ b/ext/tk/lib/tk/msgcat.rb
@@ -125,6 +125,8 @@ class TkMsgCatalog < TkObject
when 2 # src and trans, or, trans_list and enc
if args[0].kind_of?(Array)
+ # trans_list
+ self.set_translation_list(loc, *args)
else
#self.set_translation(loc, args[0], Tk::UTF8_String.new(args[1]))
self.set_translation(loc, *args)
@@ -199,7 +201,11 @@ class TkMsgCatalog < TkObject
file = File.join(dir, loc + self::MSGCAT_EXT)
if File.readable?(file)
count += 1
- eval(open(file){|f| f.read})
+ if TkCore::WITH_ENCODING
+ eval(IO.read(file, :encoding=>"ASCII-8BIT"))
+ else
+ eval(IO.read(file))
+ end
end
}
count
@@ -215,7 +221,11 @@ class TkMsgCatalog < TkObject
file = File.join(dir, loc + @msgcat_ext)
if File.readable?(file)
count += 1
- @namespace.eval(open(file){|f| f.read})
+ if TkCore::WITH_ENCODING
+ @namespace.eval(IO.read(file, :encoding=>"ASCII-8BIT"))
+ else
+ @namespace.eval(IO.read(file))
+ end
end
}
count
@@ -229,30 +239,21 @@ class TkMsgCatalog < TkObject
def self.set_translation(locale, src_str, trans_str=None, enc='utf-8')
if trans_str && trans_str != None
trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc))
- Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset',
- locale,
- _get_eval_string(src_str, true),
- trans_str))
+ Tk.UTF8_String(ip_eval_without_enc("::msgcat::mcset {#{locale}} {#{_get_eval_string(src_str, true)}} {#{trans_str}}"))
else
- Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset',
- locale,
- _get_eval_string(src_str, true)))
+ Tk.UTF8_String(ip_eval_without_enc("::msgcat::mcset {#{locale}} {#{_get_eval_string(src_str, true)}}"))
end
end
def set_translation(locale, src_str, trans_str=None, enc='utf-8')
if trans_str && trans_str != None
trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc))
Tk.UTF8_String(@namespace.eval{
- tk_call_without_enc('::msgcat::mcset',
- locale,
- _get_eval_string(src_str, true),
- trans_str)
+ ip_eval_without_enc("::msgcat::mcset {#{locale}} {#{_get_eval_string(src_str, true)}} {#{trans_str}}")
})
else
Tk.UTF8_String(@namespace.eval{
- tk_call_without_enc('::msgcat::mcset',
- locale,
- _get_eval_string(src_str, true))})
+ ip_eval_without_enc("::msgcat::mcset {#{locale}} {#{_get_eval_string(src_str, true)}}")
+ })
end
end
@@ -262,12 +263,13 @@ class TkMsgCatalog < TkObject
trans_list.each{|src, trans|
if trans && trans != None
list << _get_eval_string(src, true)
- list << Tk.UTF8_Stirng(_toUTF8(trans, enc))
+ list << Tk.UTF8_String(_toUTF8(trans, enc))
else
list << _get_eval_string(src, true) << ''
end
}
- number(tk_call_without_enc('::msgcat::mcmset', locale, list))
+ #number(tk_call_without_enc('::msgcat::mcmset', locale, list))
+ number(ip_eval_without_enc("::msgcat::mcmset {#{locale}} {#{_get_eval_string(list)}}"))
end
def set_translation_list(locale, trans_list, enc='utf-8')
# trans_list ::= [ [src, trans], [src, trans], ... ]
@@ -281,7 +283,8 @@ class TkMsgCatalog < TkObject
end
}
number(@namespace.eval{
- tk_call_without_enc('::msgcat::mcmset', locale, list)
+ #tk_call_without_enc('::msgcat::mcmset', locale, list)
+ ip_eval_without_enc("::msgcat::mcmset {#{locale}} {#{_get_eval_string(list)}}")
})
end
diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb
index 4af891995e..0119ba5ef7 100644
--- a/ext/tk/lib/tk/namespace.rb
+++ b/ext/tk/lib/tk/namespace.rb
@@ -325,12 +325,7 @@ class TkNamespace < TkObject
def code(script = Proc.new)
if script.kind_of?(String)
cmd = proc{|*args|
- if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
- obj = ScopeArgs.new(@fullname,*args)
- ret = obj.instance_exec(obj, script)
- else
- ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
- end
+ ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
id = ret.object_id
TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
id
diff --git a/ext/tk/lib/tkextlib/tktable/tktable.rb b/ext/tk/lib/tkextlib/tktable/tktable.rb
index bc7a6c9a2e..f7074655ed 100644
--- a/ext/tk/lib/tkextlib/tktable/tktable.rb
+++ b/ext/tk/lib/tkextlib/tktable/tktable.rb
@@ -70,7 +70,7 @@ module Tk::TkTable::ConfigMethod
private :__item_strval_optkeys
def __item_val2ruby_optkeys(id) # { key=>method, ... }
- super(id).update('window'=>proc{|v| window(v)})
+ super(id).update('window'=>proc{|k,v| window(v)})
end
private :__item_val2ruby_optkeys
diff --git a/ext/tk/sample/demos-en/tree.rb b/ext/tk/sample/demos-en/tree.rb
index cd62ba8c9b..69154ee076 100644
--- a/ext/tk/sample/demos-en/tree.rb
+++ b/ext/tk/sample/demos-en/tree.rb
@@ -67,7 +67,7 @@ def populate_tree(tree, node)
path = tree.get(node, :fullpath)
tree.delete(tree.children(node))
Dir.glob("#{path}/*").sort.each{|f|
- type = File.ftype(f)
+ type = File.ftype(f) rescue nil
id = tree.insert(node, :end,
:text=>File.basename(f), :values=>[f, type]).id
if type == 'directory'
diff --git a/ext/tk/sample/demos-en/widget b/ext/tk/sample/demos-en/widget
index e6510c7e45..3778929d9c 100644
--- a/ext/tk/sample/demos-en/widget
+++ b/ext/tk/sample/demos-en/widget
@@ -683,7 +683,7 @@ def eval_samplecode(code, file=nil)
end
}
}
- Tk.update
+ Tk.update rescue nil
end
# invoke --
@@ -699,7 +699,7 @@ def invoke(txt, idx)
cursor = txt.cget('cursor')
txt.cursor('watch')
- Tk.update
+ Tk.update rescue nil
# eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
# Tk.update
eval_samplecode(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, tag[5..-1] + '.rb')
@@ -1058,7 +1058,7 @@ if ARGV[0] == '-n'
no_launcher = true if ARGV.size > 0
else
# show the root widget to make it lower then demo windows
- Tk.update
+ Tk.update rescue nil
end
ARGV.each{|cmd|
if cmd =~ /(.*).rb/
diff --git a/ext/tk/sample/demos-jp/tree.rb b/ext/tk/sample/demos-jp/tree.rb
index 00d715282b..f6855445ca 100644
--- a/ext/tk/sample/demos-jp/tree.rb
+++ b/ext/tk/sample/demos-jp/tree.rb
@@ -68,7 +68,7 @@ def populate_tree(tree, node)
path = tree.get(node, :fullpath)
tree.delete(tree.children(node))
Dir.glob("#{path}/*").sort.each{|f|
- type = File.ftype(f)
+ type = File.ftype(f) rescue nil
id = tree.insert(node, :end,
:text=>File.basename(f), :values=>[f, type]).id
if type == 'directory'
diff --git a/ext/tk/sample/demos-jp/widget b/ext/tk/sample/demos-jp/widget
index fc3c084e9a..ae91031fb6 100644
--- a/ext/tk/sample/demos-jp/widget
+++ b/ext/tk/sample/demos-jp/widget
@@ -740,7 +740,7 @@ def eval_samplecode(code, file=nil)
end
}
}
- Tk.update
+ Tk.update rescue nil
end
# ¥Æ¥­¥¹¥È¾å¤Ç¤Î click ¤ËÂФ¹¤ëÆ°ºî
@@ -750,7 +750,7 @@ def invoke(txt, idx)
cursor = txt.cget('cursor')
txt.cursor('watch')
- Tk.update
+ Tk.update rescue nil
# eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
# Tk.update
eval_samplecode(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, tag[5..-1] + '.rb')
@@ -1094,7 +1094,7 @@ if ARGV[0] == '-n'
no_launcher = true if ARGV.size > 0
else
# show the root widget to make it lower then demo windows
- Tk.update
+ Tk.update rescue nil
end
ARGV.each{|cmd|
if cmd =~ /(.*).rb/
diff --git a/ext/tk/sample/scrollframe.rb b/ext/tk/sample/scrollframe.rb
index e340e1da3c..e9d8af7ebf 100644
--- a/ext/tk/sample/scrollframe.rb
+++ b/ext/tk/sample/scrollframe.rb
@@ -13,6 +13,8 @@
#
require 'tk'
+module Tk::RbWidget; end
+
class Tk::RbWidget::ScrollFrame < TkFrame
include TkComposite
diff --git a/ext/tk/stubs.c b/ext/tk/stubs.c
index dd475c3455..636bae0801 100644
--- a/ext/tk/stubs.c
+++ b/ext/tk/stubs.c
@@ -83,8 +83,8 @@ _nativethread_consistency_check(ip)
# define DL_SYM GetProcAddress
# define TCL_INDEX 4
# define TK_INDEX 3
-# define TCL_NAME "tcl89%s"
-# define TK_NAME "tk89%s"
+# define TCL_NAME "tcl89"
+# define TK_NAME "tk89"
# undef DLEXT
# define DLEXT ".dll"
#elif defined HAVE_DLOPEN
@@ -94,8 +94,8 @@ _nativethread_consistency_check(ip)
# define DL_SYM dlsym
# define TCL_INDEX 8
# define TK_INDEX 7
-# define TCL_NAME "libtcl8.9%s"
-# define TK_NAME "libtk8.9%s"
+# define TCL_NAME "libtcl8.9"
+# define TK_NAME "libtk8.9"
# if defined(__APPLE__) && defined(__MACH__) /* Mac OS X */
# undef DLEXT
# define DLEXT ".dylib"
@@ -116,7 +116,6 @@ ruby_open_tcl_dll(appname)
void (*p_Tcl_FindExecutable)(const char *);
int n;
char *ruby_tcl_dll = 0;
- char tcl_name[20];
if (tcl_dll) return TCLTK_STUBS_OK;
@@ -127,7 +126,7 @@ ruby_open_tcl_dll(appname)
if (ruby_tcl_dll) {
tcl_dll = (DL_HANDLE)DL_OPEN(ruby_tcl_dll);
} else {
- snprintf(tcl_name, sizeof tcl_name, TCL_NAME, DLEXT);
+ char tcl_name[] = TCL_NAME DLEXT;
/* examine from 8.9 to 8.1 */
for (n = '9'; n > '0'; n--) {
tcl_name[TCL_INDEX] = n;
@@ -162,7 +161,6 @@ ruby_open_tk_dll()
{
int n;
char *ruby_tk_dll = 0;
- char tk_name[20];
if (!tcl_dll) {
/* int ret = ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */
@@ -176,7 +174,7 @@ ruby_open_tk_dll()
if (ruby_tk_dll) {
tk_dll = (DL_HANDLE)DL_OPEN(ruby_tk_dll);
} else {
- snprintf(tk_name, sizeof tk_name, TK_NAME, DLEXT);
+ char tk_name[] = TK_NAME DLEXT;
/* examine from 8.9 to 8.1 */
for (n = '9'; n > '0'; n--) {
tk_name[TK_INDEX] = n;
diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c
index 312b0c05eb..068babfe93 100644
--- a/ext/tk/tcltklib.c
+++ b/ext/tk/tcltklib.c
@@ -839,15 +839,14 @@ create_ip_exc(interp, exc, fmt, va_alist)
#endif
{
va_list args;
- char buf[BUFSIZ];
+ VALUE msg;
VALUE einfo;
struct tcltkip *ptr = get_ip(interp);
va_init_list(args,fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- buf[BUFSIZ - 1] = '\0';
+ msg = rb_vsprintf(fmt, args);
va_end(args);
- einfo = rb_exc_new2(exc, buf);
+ einfo = rb_exc_new3(exc, msg);
rb_ivar_set(einfo, ID_at_interp, interp);
if (ptr) {
Tcl_ResetResult(ptr->ip);
@@ -6641,7 +6640,7 @@ ip_make_safe_core(interp, argc, argv)
if (Tcl_MakeSafe(ptr->ip) == TCL_ERROR) {
/* return rb_exc_new2(rb_eRuntimeError,
Tcl_GetStringResult(ptr->ip)); */
- return create_ip_exc(interp, rb_eRuntimeError,
+ return create_ip_exc(interp, rb_eRuntimeError, "%s",
Tcl_GetStringResult(ptr->ip));
}
@@ -9331,7 +9330,7 @@ ip_get_variable2_core(interp, argc, argv)
volatile VALUE exc;
/* exc = rb_exc_new2(rb_eRuntimeError,
Tcl_GetStringResult(ptr->ip)); */
- exc = create_ip_exc(interp, rb_eRuntimeError,
+ exc = create_ip_exc(interp, rb_eRuntimeError, "%s",
Tcl_GetStringResult(ptr->ip));
/* Tcl_Release(ptr->ip); */
rbtk_release_ip(ptr);
@@ -9470,7 +9469,7 @@ ip_set_variable2_core(interp, argc, argv)
volatile VALUE exc;
/* exc = rb_exc_new2(rb_eRuntimeError,
Tcl_GetStringResult(ptr->ip)); */
- exc = create_ip_exc(interp, rb_eRuntimeError,
+ exc = create_ip_exc(interp, rb_eRuntimeError, "%s",
Tcl_GetStringResult(ptr->ip));
/* Tcl_Release(ptr->ip); */
rbtk_release_ip(ptr);
@@ -9590,7 +9589,7 @@ ip_unset_variable2_core(interp, argc, argv)
if (FIX2INT(flag) & TCL_LEAVE_ERR_MSG) {
/* return rb_exc_new2(rb_eRuntimeError,
Tcl_GetStringResult(ptr->ip)); */
- return create_ip_exc(interp, rb_eRuntimeError,
+ return create_ip_exc(interp, rb_eRuntimeError, "%s",
Tcl_GetStringResult(ptr->ip));
}
return Qfalse;
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index acc2fea39d..686daf67de 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -1185,19 +1185,18 @@ static void
ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...)
{
va_list args;
- char buf[BUFSIZ];
+ VALUE msg;
VALUE err_msg;
va_init_list(args, fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
+ msg = rb_vsprintf(fmt, args);
va_end(args);
err_msg = ole_hresult2msg(hr);
if(err_msg != Qnil) {
- rb_raise(ecs, "%s\n%s", buf, StringValuePtr(err_msg));
- }
- else {
- rb_raise(ecs, "%s", buf);
+ rb_str_cat2(msg, "\n");
+ rb_str_append(msg, err_msg);
}
+ rb_exc_raise(rb_exc_new3(ecs, msg));
}
void
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index d5909d60c0..b916910e3e 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -294,11 +294,8 @@ raise_zlib_error(int err, const char *msg)
rb_sys_fail(msg);
/* no return */
default:
- {
- char buf[BUFSIZ];
- snprintf(buf, BUFSIZ, "unknown zlib error %d: %s", err, msg);
- exc = rb_exc_new2(cZError, buf);
- }
+ exc = rb_exc_new3(cZError,
+ rb_sprintf("unknown zlib error %d: %s", err, msg));
}
rb_exc_raise(exc);
@@ -1337,6 +1334,7 @@ rb_deflate_init_copy(VALUE self, VALUE orig)
Data_Get_Struct(self, struct zstream, z1);
z2 = get_zstream(orig);
+ if (z1 == z2) return self;
err = deflateCopy(&z1->stream, &z2->stream);
if (err != Z_OK) {
raise_zlib_error(err, 0);
diff --git a/file.c b/file.c
index c60de23302..e7e0885e98 100644
--- a/file.c
+++ b/file.c
@@ -2784,6 +2784,34 @@ rb_enc_path_end(const char *path, const char *end, rb_encoding *enc)
return chompdirsep(path, end, enc);
}
+char *
+rb_path_next(const char *path)
+{
+ rb_warn("rb_path_next() is deprecated");
+ return rb_enc_path_next(path, path + strlen(path), rb_filesystem_encoding());
+}
+
+char *
+rb_path_skip_prefix(const char *path)
+{
+ rb_warn("rb_path_skip_prefix() is deprecated");
+ return rb_enc_path_skip_prefix(path, path + strlen(path), rb_filesystem_encoding());
+}
+
+char *
+rb_path_last_separator(const char *path)
+{
+ rb_warn("rb_path_last_separator() is deprecated");
+ return rb_enc_path_last_separator(path, path + strlen(path), rb_filesystem_encoding());
+}
+
+char *rb_path_end(const char *path)
+{
+ rb_warn("rb_path_end() is deprecated");
+ return rb_enc_path_end(path, path + strlen(path), rb_filesystem_encoding());
+}
+
+
#if USE_NTFS
static char *
ntfs_tail(const char *path, const char *end, rb_encoding *enc)
@@ -3629,6 +3657,13 @@ ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encodin
return p;
}
+const char *
+ruby_find_basename(const char *name, long *baselen, long *alllen)
+{
+ rb_warn("ruby_find_basename() is deprecated");
+ return ruby_enc_find_basename(name, baselen, alllen, rb_filesystem_encoding());
+}
+
/*
* call-seq:
* File.basename(file_name [, suffix] ) -> base_name
@@ -3818,6 +3853,13 @@ ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc)
return e;
}
+const char *
+ruby_find_extname(const char *name, long *len)
+{
+ rb_warn("ruby_find_extname() is deprecated");
+ return ruby_enc_find_extname(name, len, rb_filesystem_encoding());
+}
+
/*
* call-seq:
* File.extname(path) -> string
diff --git a/gc.c b/gc.c
index 0f84e22966..6eaf4ae491 100644
--- a/gc.c
+++ b/gc.c
@@ -377,6 +377,7 @@ typedef struct rb_objspace {
int dont_gc;
int dont_lazy_sweep;
int during_gc;
+ rb_atomic_t finalizing;
} flags;
struct {
st_table *table;
@@ -415,6 +416,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
#define heaps_freed objspace->heap.freed
#define dont_gc objspace->flags.dont_gc
#define during_gc objspace->flags.during_gc
+#define finalizing objspace->flags.finalizing
#define finalizer_table objspace->final.table
#define deferred_final_list objspace->final.deferred
#define global_List objspace->global_list
@@ -2175,7 +2177,7 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot)
}
objspace->heap.final_num += final_num;
- if (deferred_final_list) {
+ if (deferred_final_list && !finalizing) {
rb_thread_t *th = GET_THREAD();
if (th) {
RUBY_VM_SET_FINALIZER_INTERRUPT(th);
@@ -3042,10 +3044,9 @@ run_final(rb_objspace_t *objspace, VALUE obj)
static void
finalize_deferred(rb_objspace_t *objspace)
{
- RVALUE *p = deferred_final_list;
- deferred_final_list = 0;
+ RVALUE *p;
- if (p) {
+ while ((p = ATOMIC_PTR_EXCHANGE(deferred_final_list, 0)) != 0) {
finalize_list(objspace, p);
}
}
@@ -3053,7 +3054,10 @@ finalize_deferred(rb_objspace_t *objspace)
void
rb_gc_finalize_deferred(void)
{
- finalize_deferred(&rb_objspace);
+ rb_objspace_t *objspace = &rb_objspace;
+ if (ATOMIC_EXCHANGE(finalizing, 1)) return;
+ finalize_deferred(objspace);
+ ATOMIC_SET(finalizing, 0);
}
struct force_finalize_list {
@@ -3093,6 +3097,8 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
finalize_deferred(objspace);
assert(deferred_final_list == 0);
+ if (ATOMIC_EXCHANGE(finalizing, 1)) return;
+
/* force to run finalizer */
while (finalizer_table->num_entries) {
struct force_finalize_list *list = 0;
@@ -3147,6 +3153,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
st_free_table(finalizer_table);
finalizer_table = 0;
+ ATOMIC_SET(finalizing, 0);
}
void
@@ -3154,7 +3161,7 @@ rb_gc(void)
{
rb_objspace_t *objspace = &rb_objspace;
garbage_collect(objspace);
- finalize_deferred(objspace);
+ if (!finalizing) finalize_deferred(objspace);
free_unused_heaps(objspace);
}
diff --git a/hash.c b/hash.c
index fbd82374eb..3111b25c09 100644
--- a/hash.c
+++ b/hash.c
@@ -442,6 +442,11 @@ rb_hash_s_try_convert(VALUE dummy, VALUE hash)
return rb_check_hash_type(hash);
}
+struct rehash_arg {
+ VALUE hash;
+ st_table *tbl;
+};
+
static int
rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
{
@@ -474,6 +479,7 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
static VALUE
rb_hash_rehash(VALUE hash)
{
+ VALUE tmp;
st_table *tbl;
if (RHASH(hash)->iter_lev > 0) {
@@ -482,10 +488,14 @@ rb_hash_rehash(VALUE hash)
rb_hash_modify_check(hash);
if (!RHASH(hash)->ntbl)
return hash;
+ tmp = hash_alloc(0);
tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries);
+ RHASH(tmp)->ntbl = tbl;
+
rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl);
st_free_table(RHASH(hash)->ntbl);
RHASH(hash)->ntbl = tbl;
+ RHASH(tmp)->ntbl = 0;
return hash;
}
@@ -824,18 +834,6 @@ struct shift_var {
};
static int
-shift_i(VALUE key, VALUE value, VALUE arg)
-{
- struct shift_var *var = (struct shift_var *)arg;
-
- if (key == Qundef) return ST_CONTINUE;
- if (var->key != Qundef) return ST_STOP;
- var->key = key;
- var->val = value;
- return ST_DELETE;
-}
-
-static int
shift_i_safe(VALUE key, VALUE value, VALUE arg)
{
struct shift_var *var = (struct shift_var *)arg;
@@ -866,16 +864,20 @@ rb_hash_shift(VALUE hash)
rb_hash_modify(hash);
var.key = Qundef;
- rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i,
- (VALUE)&var);
+ if (RHASH(hash)->iter_lev == 0) {
+ if (st_shift(RHASH(hash)->ntbl, &var.key, &var.val)) {
+ return rb_assoc_new(var.key, var.val);
+ }
+ }
+ else {
+ rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
- if (var.key != Qundef) {
- if (RHASH(hash)->iter_lev > 0) {
+ if (var.key != Qundef) {
rb_hash_delete_key(hash, var.key);
+ return rb_assoc_new(var.key, var.val);
}
- return rb_assoc_new(var.key, var.val);
}
- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
+ if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil);
}
else {
diff --git a/id.c b/id.c
index 89ae4a4e77..95059caaed 100644
--- a/id.c
+++ b/id.c
@@ -35,6 +35,7 @@ Init_id(void)
REGISTER_SYMID(idEach, "each");
REGISTER_SYMID(idLength, "length");
REGISTER_SYMID(idSize, "size");
+ REGISTER_SYMID(idProc, "proc");
REGISTER_SYMID(idLambda, "lambda");
REGISTER_SYMID(idIntern, "intern");
REGISTER_SYMID(idGets, "gets");
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 6e1c2c2d90..7f1b078136 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -36,6 +36,10 @@ extern "C" {
#include <sys/types.h>
#endif
+#if defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
#include "ruby/st.h"
#if defined __GNUC__ && __GNUC__ >= 4
@@ -166,7 +170,6 @@ VALUE rb_Complex(VALUE, VALUE);
VALUE rb_class_boot(VALUE);
VALUE rb_class_new(VALUE);
VALUE rb_mod_init_copy(VALUE, VALUE);
-VALUE rb_class_init_copy(VALUE, VALUE);
VALUE rb_singleton_class_clone(VALUE);
void rb_singleton_class_attached(VALUE,VALUE);
VALUE rb_make_metaclass(VALUE, VALUE);
@@ -347,7 +350,8 @@ VALUE rb_require_safe(VALUE, int);
void rb_obj_call_init(VALUE, int, VALUE*);
VALUE rb_class_new_instance(int, VALUE*, VALUE);
VALUE rb_block_proc(void);
-VALUE rb_f_lambda(void);
+DEPRECATED(VALUE rb_f_lambda(void));
+VALUE rb_block_lambda(void);
VALUE rb_proc_new(VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE);
VALUE rb_obj_is_proc(VALUE);
VALUE rb_proc_call(VALUE, VALUE);
@@ -358,6 +362,7 @@ VALUE rb_binding_new(void);
VALUE rb_obj_method(VALUE, VALUE);
VALUE rb_obj_is_method(VALUE);
VALUE rb_method_call(int, VALUE*, VALUE);
+VALUE rb_method_call_with_block(int, VALUE *, VALUE, VALUE);
int rb_mod_method_arity(VALUE, ID);
int rb_obj_method_arity(VALUE, ID);
VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*);
@@ -394,6 +399,7 @@ void rb_thread_atfork_before_exec(void);
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
+VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
/* dir.c */
VALUE rb_dir_getwd(void);
/* file.c */
@@ -408,9 +414,15 @@ int rb_find_file_ext_safe(VALUE*, const char* const*, int);
VALUE rb_find_file_safe(VALUE, int);
int rb_find_file_ext(VALUE*, const char* const*);
VALUE rb_find_file(VALUE);
+DEPRECATED(char *rb_path_next(const char *));
+DEPRECATED(char *rb_path_skip_prefix(const char *));
+DEPRECATED(char *rb_path_last_separator(const char *));
+DEPRECATED(char *rb_path_end(const char *));
VALUE rb_file_directory_p(VALUE,VALUE);
VALUE rb_str_encode_ospath(VALUE);
int rb_is_absolute_path(const char *);
+DEPRECATED(const char *ruby_find_basename(const char *name, long *baselen, long *alllen));
+DEPRECATED(const char *ruby_find_extname(const char *name, long *len));
/* gc.c */
void ruby_set_stack_size(size_t);
NORETURN(void rb_memerror(void));
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 2f97b33bc4..453a6039a9 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1153,6 +1153,7 @@ VALUE rb_funcall(VALUE, ID, int, ...);
VALUE rb_funcall2(VALUE, ID, int, const VALUE*);
VALUE rb_funcall3(VALUE, ID, int, const VALUE*);
VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*);
+VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE);
int rb_scan_args(int, const VALUE*, const char*, ...);
VALUE rb_call_super(int, const VALUE*);
diff --git a/include/ruby/st.h b/include/ruby/st.h
index 50f2a75328..68cc511809 100644
--- a/include/ruby/st.h
+++ b/include/ruby/st.h
@@ -109,6 +109,7 @@ st_table *st_init_strcasetable(void);
st_table *st_init_strcasetable_with_size(st_index_t);
int st_delete(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */
int st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t);
+int st_shift(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */
int st_insert(st_table *, st_data_t, st_data_t);
int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t));
int st_lookup(st_table *, st_data_t, st_data_t *);
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index 99382f48e3..2801697f16 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -315,6 +315,20 @@ extern FILE *rb_w32_fsopen(const char *, const char *, int);
#endif
#include <float.h>
+
+#if defined _MSC_VER && _MSC_VER >= 1800 && defined INFINITY
+#pragma warning(push)
+#pragma warning(disable:4756)
+static inline float
+rb_infinity_float(void)
+{
+ return INFINITY;
+}
+#pragma warning(pop)
+#undef INFINITY
+#define INFINITY rb_infinity_float()
+#endif
+
#if !defined __MINGW32__ || defined __NO_ISOCEXT
#ifndef isnan
#define isnan(x) _isnan(x)
diff --git a/internal.h b/internal.h
index 59c928462e..6afea9ce2e 100644
--- a/internal.h
+++ b/internal.h
@@ -138,6 +138,8 @@ void Init_newline(void);
int rb_num_to_uint(VALUE val, unsigned int *ret);
int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl);
double ruby_float_mod(double x, double y);
+VALUE rb_int_succ(VALUE num);
+VALUE rb_int_pred(VALUE num);
/* object.c */
VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
@@ -165,6 +167,7 @@ size_t rb_strftime_timespec(char *s, size_t maxsize, const char *format, const s
/* string.c */
int rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p);
+VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg);
/* struct.c */
VALUE rb_struct_init_copy(VALUE copy, VALUE s);
diff --git a/io.c b/io.c
index 57164d1042..7c8f2c9762 100644
--- a/io.c
+++ b/io.c
@@ -1816,15 +1816,31 @@ io_bufread(char *ptr, long len, rb_io_t *fptr)
return len - n;
}
+struct bufread_arg {
+ char *str_ptr;
+ long len;
+ rb_io_t *fptr;
+};
+
+static VALUE
+bufread_call(VALUE arg)
+{
+ struct bufread_arg *p = (struct bufread_arg *)arg;
+ p->len = io_bufread(p->str_ptr, p->len, p->fptr);
+ return Qundef;
+}
+
static long
io_fread(VALUE str, long offset, rb_io_t *fptr)
{
long len;
+ struct bufread_arg arg;
- rb_str_locktmp(str);
- len = io_bufread(RSTRING_PTR(str) + offset, RSTRING_LEN(str) - offset,
- fptr);
- rb_str_unlocktmp(str);
+ arg.str_ptr = RSTRING_PTR(str) + offset;
+ arg.len = RSTRING_LEN(str) - offset;
+ arg.fptr = fptr;
+ rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
+ len = arg.len;
if (len < 0) rb_sys_fail_path(fptr->pathv);
return len;
}
@@ -2124,12 +2140,27 @@ rb_io_set_nonblock(rb_io_t *fptr)
}
}
+struct read_internal_arg {
+ int fd;
+ char *str_ptr;
+ long len;
+};
+
+static VALUE
+read_internal_call(VALUE arg)
+{
+ struct read_internal_arg *p = (struct read_internal_arg *)arg;
+ p->len = rb_read_internal(p->fd, p->str_ptr, p->len);
+ return Qundef;
+}
+
static VALUE
io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
{
rb_io_t *fptr;
VALUE length, str;
long n, len;
+ struct read_internal_arg arg;
rb_scan_args(argc, argv, "11", &length, &str);
@@ -2154,9 +2185,11 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
if (nonblock) {
rb_io_set_nonblock(fptr);
}
- rb_str_locktmp(str);
- n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
- rb_str_unlocktmp(str);
+ arg.fd = fptr->fd;
+ arg.str_ptr = RSTRING_PTR(str);
+ arg.len = len;
+ rb_str_locktmp_ensure(str, read_internal_call, (VALUE)&arg);
+ n = arg.len;
if (n < 0) {
if (!nonblock && rb_io_wait_readable(fptr->fd))
goto again;
@@ -3151,7 +3184,11 @@ io_getc(rb_io_t *fptr, rb_encoding *enc)
}
else {
io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
- cr = ISASCII(r) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
+ cr = ENC_CODERANGE_VALID;
+ if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
+ ISASCII(RSTRING_PTR(str)[0])) {
+ cr = ENC_CODERANGE_7BIT;
+ }
}
str = io_enc_str(str, fptr);
ENC_CODERANGE_SET(str, cr);
@@ -4027,11 +4064,16 @@ rb_io_close_read(VALUE io)
write_io = GetWriteIO(io);
if (io != write_io) {
rb_io_t *wfptr;
- rb_io_fptr_cleanup(fptr, FALSE);
GetOpenFile(write_io, wfptr);
+ wfptr->pid = fptr->pid;
+ fptr->pid = 0;
RFILE(io)->fptr = wfptr;
- RFILE(write_io)->fptr = NULL;
- rb_io_fptr_finalize(fptr);
+ /* bind to write_io temporarily to get rid of memory/fd leak */
+ fptr->tied_io_for_writing = 0;
+ fptr->mode &= ~FMODE_DUPLEX;
+ RFILE(write_io)->fptr = fptr;
+ rb_io_fptr_cleanup(fptr, FALSE);
+ /* should not finalize fptr because another thread may be reading it */
return Qnil;
}
@@ -4087,12 +4129,12 @@ rb_io_close_write(VALUE io)
rb_raise(rb_eIOError, "closing non-duplex IO for writing");
}
- rb_io_close(write_io);
if (io != write_io) {
GetOpenFile(io, fptr);
fptr->tied_io_for_writing = 0;
fptr->mode &= ~FMODE_DUPLEX;
}
+ rb_io_close(write_io);
return Qnil;
}
@@ -4171,6 +4213,7 @@ rb_io_syswrite(VALUE io, VALUE str)
}
n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
+ RB_GC_GUARD(str);
if (n == -1) rb_sys_fail_path(fptr->pathv);
@@ -4199,6 +4242,7 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
VALUE len, str;
rb_io_t *fptr;
long n, ilen;
+ struct read_internal_arg arg;
rb_scan_args(argc, argv, "11", &len, &str);
ilen = NUM2LONG(len);
@@ -4218,8 +4262,11 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
rb_io_check_closed(fptr);
rb_str_locktmp(str);
- n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen);
- rb_str_unlocktmp(str);
+ arg.fd = fptr->fd;
+ arg.str_ptr = RSTRING_PTR(str);
+ arg.len = ilen;
+ rb_ensure(read_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
+ n = arg.len;
if (n == -1) {
rb_sys_fail_path(fptr->pathv);
diff --git a/iseq.c b/iseq.c
index 721277a7d3..f680e60839 100644
--- a/iseq.c
+++ b/iseq.c
@@ -450,6 +450,7 @@ iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
VALUE type, body, locals, args, exception;
st_data_t iseq_type;
+ static struct st_table *type_map_cache = 0;
struct st_table *type_map = 0;
rb_iseq_t *iseq;
rb_compile_option_t option;
@@ -488,7 +489,9 @@ iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
GetISeqPtr(iseqval, iseq);
iseq->self = iseqval;
+ type_map = type_map_cache;
if (type_map == 0) {
+ struct st_table *cached_map;
type_map = st_init_numtable();
st_insert(type_map, ID2SYM(rb_intern("top")), ISEQ_TYPE_TOP);
st_insert(type_map, ID2SYM(rb_intern("method")), ISEQ_TYPE_METHOD);
@@ -499,6 +502,11 @@ iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
st_insert(type_map, ID2SYM(rb_intern("eval")), ISEQ_TYPE_EVAL);
st_insert(type_map, ID2SYM(rb_intern("main")), ISEQ_TYPE_MAIN);
st_insert(type_map, ID2SYM(rb_intern("defined_guard")), ISEQ_TYPE_DEFINED_GUARD);
+ cached_map = ATOMIC_PTR_CAS(type_map_cache, (struct st_table *)0, type_map);
+ if (cached_map) {
+ st_free_table(type_map);
+ type_map = cached_map;
+ }
}
if (st_lookup(type_map, type, &iseq_type) == 0) {
diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
index e961b16474..d7ec8981d7 100644
--- a/lib/cgi/core.rb
+++ b/lib/cgi/core.rb
@@ -478,10 +478,12 @@ class CGI
bufsize = 10 * 1024
max_count = MAX_MULTIPART_COUNT
n = 0
+ tempfiles = []
while true
(n += 1) < max_count or raise StandardError.new("too many parameters.")
## create body (StringIO or Tempfile)
body = create_body(bufsize < content_length)
+ tempfiles << body if defined?(Tempfile) && body.kind_of?(Tempfile)
class << body
if method_defined?(:path)
alias local_path path
@@ -562,6 +564,15 @@ class CGI
raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/
params.default = []
params
+ rescue Exception
+ if tempfiles
+ tempfiles.each {|t|
+ if t.path
+ t.unlink
+ end
+ }
+ end
+ raise
end # read_multipart
private :read_multipart
def create_body(is_large) #:nodoc:
diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb
index 2b6a2376ef..a680594d80 100644
--- a/lib/drb/ssl.rb
+++ b/lib/drb/ssl.rb
@@ -179,8 +179,9 @@ module DRb
end
begin
ssl = @config.accept(soc)
- ensure
- soc.close if $!
+ rescue Exception
+ soc.close
+ raise
end
self.class.new(uri, ssl, @config, true)
rescue OpenSSL::SSL::SSLError
diff --git a/lib/gserver.rb b/lib/gserver.rb
index f6f37d3a89..4dd5ad0c08 100644
--- a/lib/gserver.rb
+++ b/lib/gserver.rb
@@ -3,7 +3,7 @@
#
# Author:: John W. Small
# Documentation:: Gavin Sinclair
-# Licence:: Freeware.
+# Licence:: Ruby License
require "socket"
require "thread"
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index a7517615ff..898e4a78c9 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -300,7 +300,7 @@ end
def xsystem command, opts = nil
varpat = /\$\((\w+)\)|\$\{(\w+)\}/
if varpat =~ command
- vars = Hash.new {|h, k| h[k] = ''; ENV[k]}
+ vars = Hash.new {|h, k| h[k] = ENV[k]}
command = command.dup
nil while command.gsub!(varpat) {vars[$1||$2]}
end
@@ -619,14 +619,14 @@ def try_func(func, libs, headers = nil, &b)
try_link(<<"SRC", libs, &b) or
#{headers}
/*top*/
-#{MAIN_DOES_NOTHING}
int t() { #{decltype["volatile p"]}; p = (#{decltype[]})#{func}; return 0; }
+#{MAIN_DOES_NOTHING "t"}
SRC
call && try_link(<<"SRC", libs, &b)
#{headers}
/*top*/
-#{MAIN_DOES_NOTHING}
int t() { #{func}(); return 0; }
+#{MAIN_DOES_NOTHING "t"}
SRC
end
@@ -636,8 +636,8 @@ def try_var(var, headers = nil, &b)
try_compile(<<"SRC", &b)
#{headers}
/*top*/
-#{MAIN_DOES_NOTHING}
int t() { const volatile void *volatile p; p = &(&#{var})[0]; return 0; }
+#{MAIN_DOES_NOTHING "t"}
SRC
end
@@ -938,18 +938,31 @@ def have_header(header, preheaders = nil, &b)
end
# Returns whether or not the given +framework+ can be found on your system.
-# If found, a macro is passed as a preprocessor constant to the compiler using
-# the framework name, in uppercase, prepended with 'HAVE_FRAMEWORK_'.
+# If found, a macro is passed as a preprocessor constant to the compiler
+# using the framework name, in uppercase, prepended with +HAVE_FRAMEWORK_+.
#
-# For example, if have_framework('Ruby') returned true, then the HAVE_FRAMEWORK_RUBY
-# preprocessor macro would be passed to the compiler.
+# For example, if <code>have_framework('Ruby')</code> returned true, then
+# the +HAVE_FRAMEWORK_RUBY+ preprocessor macro would be passed to the
+# compiler.
#
+# If +fw+ is a pair of the framework name and its header file name
+# that header file is checked, instead of the normally used header
+# file which is named same as the framework.
def have_framework(fw, &b)
+ if Array === fw
+ fw, header = *fw
+ else
+ header = "#{fw}.h"
+ end
checking_for fw do
- src = cpp_include("#{fw}/#{fw}.h") << "\n" "int main(void){return 0;}"
- if try_link(src, opt = "-framework #{fw}", &b)
+ src = cpp_include("#{fw}/#{header}") << "\n" "int main(void){return 0;}"
+ opt = " -framework #{fw}"
+ if try_link(src, "-ObjC#{opt}", &b)
$defs.push(format("-DHAVE_FRAMEWORK_%s", fw.tr_cpp))
- $LDFLAGS << " " << opt
+ # TODO: non-worse way than this hack, to get rid of separating
+ # option and its argument.
+ $LDFLAGS << " -ObjC" unless /(\A|\s)-ObjC(\s|\z)/ =~ $LDFLAGS
+ $LDFLAGS << opt
true
else
false
@@ -1002,8 +1015,8 @@ def have_struct_member(type, member, headers = nil, &b)
if try_compile(<<"SRC", &b)
#{cpp_include(headers)}
/*top*/
-#{MAIN_DOES_NOTHING}
int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
+#{MAIN_DOES_NOTHING "s"}
SRC
$defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp))
$defs.push(format("-DHAVE_ST_%s", member.tr_cpp)) # backward compatibility
@@ -1243,8 +1256,8 @@ def scalar_ptr_type?(type, member = nil, headers = nil, &b)
#{cpp_include(headers)}
/*top*/
volatile #{type} conftestval;
-#{MAIN_DOES_NOTHING}
int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
+#{MAIN_DOES_NOTHING "t"}
SRC
end
@@ -1255,8 +1268,8 @@ def scalar_type?(type, member = nil, headers = nil, &b)
#{cpp_include(headers)}
/*top*/
volatile #{type} conftestval;
-#{MAIN_DOES_NOTHING}
int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
+#{MAIN_DOES_NOTHING "t"}
SRC
end
@@ -2226,6 +2239,19 @@ def mkmf_failed(path)
end
end
+def MAIN_DOES_NOTHING(*refs)
+ src = MAIN_DOES_NOTHING
+ unless refs.empty?
+ src = src.sub(/\{/) do
+ $& +
+ "\n if (argc > 1000000) {\n" +
+ refs.map {|n|" printf(\"%p\", &#{n});\n"}.join("") +
+ " }\n"
+ end
+ end
+ src
+end
+
# :startdoc:
init_mkmf
@@ -2282,17 +2308,18 @@ COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(
TRY_LINK = config_string('TRY_LINK') ||
"$(CC) #{OUTFLAG}conftest $(INCFLAGS) $(CPPFLAGS) " \
"$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
-LINK_SO = config_string('LINK_SO') ||
+LINK_SO = (config_string('LINK_SO') || "").sub(/^$/) do
if CONFIG["DLEXT"] == $OBJEXT
"ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
else
"$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
"$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
end
+end
LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
RPATHFLAG = config_string('RPATHFLAG') || ''
LIBARG = config_string('LIBARG') || '-l%s'
-MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || 'int main() {return 0;}'
+MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || "int main(int argc, char **argv)\n{\n return 0;\n}"
UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} ||
%w[int short long long\ long]
diff --git a/lib/net/http.rb b/lib/net/http.rb
index fd8c802935..67de15cd27 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -623,13 +623,13 @@ module Net #:nodoc:
# Number of seconds to wait for the connection to open. Any number
# may be used, including Floats for fractional seconds. If the HTTP
# object cannot open a connection in this many seconds, it raises a
- # TimeoutError exception.
+ # TimeoutError exception. The default value is +nil+.
attr_accessor :open_timeout
# Number of seconds to wait for one block to be read (via one read(2)
# call). Any number may be used, including Floats for fractional
# seconds. If the HTTP object cannot read data in this many seconds,
- # it raises a TimeoutError exception.
+ # it raises a TimeoutError exception. The default value is 60 seconds.
attr_reader :read_timeout
# Setter for the read_timeout attribute.
@@ -638,8 +638,9 @@ module Net #:nodoc:
@read_timeout = sec
end
- # Seconds to wait for 100 Continue response. If the HTTP object does not
- # receive a response in this many seconds it sends the request body.
+ # Seconds to wait for 100 Continue response. If the HTTP object does not
+ # receive a response in this many seconds it sends the request body. The
+ # default value is +nil+.
attr_reader :continue_timeout
# Setter for the continue_timeout attribute.
@@ -1947,7 +1948,7 @@ module Net #:nodoc:
wait_for_continue sock, ver if sock.continue_timeout
if chunked?
while s = f.read(1024)
- sock.write(sprintf("%x\r\n", s.length) << s << "\r\n")
+ sock.write(sprintf("%x\r\n", s.bytesize) << s << "\r\n")
end
sock.write "0\r\n\r\n"
else
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index e0815a1892..df9ee8ce1e 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -1725,7 +1725,7 @@ module Net
# rights:: The access rights the indicated user has to the
# mailbox.
#
- MailboxACLItem = Struct.new(:user, :rights)
+ MailboxACLItem = Struct.new(:user, :rights, :mailbox)
# Net::IMAP::StatusData represents contents of the STATUS response.
#
@@ -2722,6 +2722,7 @@ module Net
token = match(T_ATOM)
name = token.value.upcase
match(T_SPACE)
+ mailbox = astring
data = []
token = lookahead
if token.symbol == T_SPACE
@@ -2737,8 +2738,7 @@ module Net
user = astring
match(T_SPACE)
rights = astring
- ##XXX data.push([user, rights])
- data.push(MailboxACLItem.new(user, rights))
+ data.push(MailboxACLItem.new(user, rights, mailbox))
end
end
return UntaggedResponse.new(name, data, @str)
@@ -2869,6 +2869,7 @@ module Net
break
when T_SPACE
shift_token
+ next
end
data.push(atom.upcase)
end
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
index 7e14246d16..ff2d77f72a 100644
--- a/lib/net/pop.rb
+++ b/lib/net/pop.rb
@@ -498,12 +498,12 @@ module Net
# Seconds to wait until a connection is opened.
# If the POP3 object cannot open a connection within this time,
- # it raises a TimeoutError exception.
+ # it raises a TimeoutError exception. The default value is 30 seconds.
attr_accessor :open_timeout
# Seconds to wait until reading one block (by one read(1) call).
# If the POP3 object cannot complete a read() within this time,
- # it raises a TimeoutError exception.
+ # it raises a TimeoutError exception. The default value is 60 seconds.
attr_reader :read_timeout
# Set the read timeout.
diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb
index 33b88f5c21..3c7af8008c 100644
--- a/lib/net/smtp.rb
+++ b/lib/net/smtp.rb
@@ -78,8 +78,9 @@ module Net
#
# This library does NOT provide functions to compose internet mails.
# You must create them by yourself. If you want better mail support,
- # try RubyMail or TMail. You can get both libraries from RAA.
- # (http://www.ruby-lang.org/en/raa.html)
+ # try RubyMail or TMail or search for alternatives in
+ # {RubyGems.org}[https://rubygems.org/] or {The Ruby
+ # Toolbox}[https://www.ruby-toolbox.com/].
#
# FYI: the official documentation on internet mail is: [RFC2822] (http://www.ietf.org/rfc/rfc2822.txt).
#
@@ -364,12 +365,12 @@ module Net
# Seconds to wait while attempting to open a connection.
# If the connection cannot be opened within this time, a
- # TimeoutError is raised.
+ # TimeoutError is raised. The default value is 30 seconds.
attr_accessor :open_timeout
# Seconds to wait while reading one block (by one read(2) call).
# If the read(2) call does not complete within this time, a
- # TimeoutError is raised.
+ # TimeoutError is raised. The default value is 60 seconds.
attr_reader :read_timeout
# Set the number of seconds to wait until timing-out a read(2)
@@ -934,11 +935,11 @@ module Net
end
def critical(&block)
- return '200 dummy reply code' if @error_occured
+ return Response.parse('200 dummy reply code') if @error_occurred
begin
return yield()
rescue Exception
- @error_occured = true
+ @error_occurred = true
raise
end
end
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index 6e24b40ba5..f0cfec94e4 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -72,7 +72,7 @@ end
# The environment variables such as http_proxy, https_proxy and ftp_proxy
# are in effect by default. :proxy => nil disables proxy.
#
-# open("http://www.ruby-lang.org/en/raa.html", :proxy => nil) {|f|
+# open("http://www.ruby-lang.org/en/", :proxy => nil) {|f|
# # ...
# }
#
@@ -508,8 +508,9 @@ module OpenURI
end
end
- # returns a list of encodings in Content-Encoding field
- # as an Array of String.
+ # Returns a list of encodings in Content-Encoding field as an array of
+ # strings.
+ #
# The encodings are downcased for canonicalization.
def content_encoding
v = @meta['content-encoding']
diff --git a/lib/optparse.rb b/lib/optparse.rb
index dcb67604e2..9eec54c027 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -1631,15 +1631,22 @@ XXX
decimal = '\d+(?:_\d+)*'
binary = 'b[01]+(?:_[01]+)*'
hex = 'x[\da-f]+(?:_[\da-f]+)*'
- octal = "0(?:[0-7]*(?:_[0-7]+)*|#{binary}|#{hex})"
+ octal = "0(?:[0-7]+(?:_[0-7]+)*|#{binary}|#{hex})?"
integer = "#{octal}|#{decimal}"
- accept(Integer, %r"\A[-+]?(?:#{integer})"io) {|s,| Integer(s) if s}
+
+ accept(Integer, %r"\A[-+]?(?:#{integer})\z"io) {|s,|
+ begin
+ Integer(s)
+ rescue ArgumentError
+ raise OptionParser::InvalidArgument, s
+ end if s
+ }
#
# Float number format, and converts to Float.
#
float = "(?:#{decimal}(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?"
- floatpat = %r"\A[-+]?#{float}"io
+ floatpat = %r"\A[-+]?#{float}\z"io
accept(Float, floatpat) {|s,| s.to_f if s}
#
@@ -1647,7 +1654,7 @@ XXX
# for float format, and Rational for rational format.
#
real = "[-+]?(?:#{octal}|#{float})"
- accept(Numeric, /\A(#{real})(?:\/(#{real}))?/io) {|s, d, n|
+ accept(Numeric, /\A(#{real})(?:\/(#{real}))?\z/io) {|s, d, n|
if n
Rational(d, n)
elsif s
@@ -1658,22 +1665,40 @@ XXX
#
# Decimal integer format, to be converted to Integer.
#
- DecimalInteger = /\A[-+]?#{decimal}/io
- accept(DecimalInteger) {|s,| s.to_i if s}
+ DecimalInteger = /\A[-+]?#{decimal}\z/io
+ accept(DecimalInteger, DecimalInteger) {|s,|
+ begin
+ Integer(s)
+ rescue ArgumentError
+ raise OptionParser::InvalidArgument, s
+ end if s
+ }
#
# Ruby/C like octal/hexadecimal/binary integer format, to be converted to
# Integer.
#
- OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))/io
- accept(OctalInteger) {|s,| s.oct if s}
+ OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))\z/io
+ accept(OctalInteger, OctalInteger) {|s,|
+ begin
+ Integer(s, 8)
+ rescue ArgumentError
+ raise OptionParser::InvalidArgument, s
+ end if s
+ }
#
# Decimal integer/float number format, to be converted to Integer for
# integer format, Float for float format.
#
DecimalNumeric = floatpat # decimal integer is allowed as float also.
- accept(DecimalNumeric) {|s,| eval(s) if s}
+ accept(DecimalNumeric, floatpat) {|s,|
+ begin
+ eval(s)
+ rescue SyntaxError
+ raise OptionParser::InvalidArgument, s
+ end if s
+ }
#
# Boolean switch, which means whether it is present or not, whether it is
diff --git a/lib/resolv.rb b/lib/resolv.rb
index 1e1889370a..9524703be4 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -186,7 +186,7 @@ class Resolv
unless @initialized
@name2addr = {}
@addr2name = {}
- open(@filename) {|f|
+ open(@filename, 'rb') {|f|
f.each {|line|
line.sub!(/#.*/, '')
addr, hostname, *aliases = line.split(/\s+/)
@@ -500,8 +500,9 @@ class Resolv
msg.rd = 1
msg.add_question(candidate, typeclass)
unless sender = senders[[candidate, nameserver, port]]
- sender = senders[[candidate, nameserver, port]] =
- requester.sender(msg, candidate, nameserver, port)
+ sender = requester.sender(msg, candidate, nameserver, port)
+ next if !sender
+ senders[[candidate, nameserver, port]] = sender
end
reply, reply_name = requester.request(sender, tout)
case reply.rcode
@@ -707,7 +708,11 @@ class Resolv
af = Socket::AF_INET
end
next if @socks_hash[bind_host]
- sock = UDPSocket.new(af)
+ begin
+ sock = UDPSocket.new(af)
+ rescue Errno::EAFNOSUPPORT
+ next # The kernel doesn't support the address family.
+ end
sock.do_not_reverse_lookup = true
sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
DNS.bind_random_port(sock, bind_host)
@@ -722,11 +727,12 @@ class Resolv
end
def sender(msg, data, host, port=Port)
+ sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
+ return nil if !sock
service = [host, port]
id = DNS.allocate_request_id(host, port)
request = msg.encode
request[0,2] = [id].pack('n')
- sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
return @senders[[service, id]] =
Sender.new(request, data, sock, host, port)
end
@@ -747,6 +753,7 @@ class Resolv
attr_reader :data
def send
+ raise "@sock is nil." if @sock.nil?
@sock.send(@msg, 0, @host, @port)
end
end
@@ -790,6 +797,7 @@ class Resolv
class Sender < Requester::Sender # :nodoc:
def send
+ raise "@sock is nil." if @sock.nil?
@sock.send(@msg, 0)
end
attr_reader :data
@@ -857,7 +865,7 @@ class Resolv
nameserver = []
search = nil
ndots = 1
- open(filename) {|f|
+ open(filename, 'rb') {|f|
f.each {|line|
line.sub!(/[#;].*/, '')
keyword, *args = line.split(/\s+/)
@@ -1457,6 +1465,7 @@ class Resolv
end
def get_bytes(len = @limit - @index)
+ raise DecodeError.new("limit exceeded") if @limit < @index + len
d = @data[@index, len]
@index += len
return d
@@ -1484,6 +1493,7 @@ class Resolv
end
def get_string
+ raise DecodeError.new("limit exceeded") if @limit <= @index
len = @data[@index].ord
raise DecodeError.new("limit exceeded") if @limit < @index + 1 + len
d = @data[@index + 1, len]
@@ -1507,6 +1517,7 @@ class Resolv
limit = @index if !limit || @index < limit
d = []
while true
+ raise DecodeError.new("limit exceeded") if @limit <= @index
case @data[@index].ord
when 0
@index += 1
@@ -1900,10 +1911,10 @@ class Resolv
attr_reader :strings
##
- # Returns the first string from +strings+.
+ # Returns the concatenated string from +strings+.
def data
- @strings[0]
+ @strings.join("")
end
def encode_rdata(msg) # :nodoc:
diff --git a/lib/rexml/document.rb b/lib/rexml/document.rb
index b945a5b76c..2f9e659772 100644
--- a/lib/rexml/document.rb
+++ b/lib/rexml/document.rb
@@ -224,7 +224,7 @@ module REXML
REXML.entity_expansion_text_limit = val
end
- # Get the entity expansion limit. By default the limit is set to 10000.
+ # Get the entity expansion limit. By default the limit is set to 10240.
#
# Deprecated. Use REXML.entity_expansion_text_limit instead.
def Document::entity_expansion_text_limit
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 7ed27461bb..480be12879 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -121,7 +121,7 @@ require "rubygems/deprecate"
# -The RubyGems Team
module Gem
- VERSION = '1.8.23'
+ VERSION = '1.8.23.2'
##
# Raised when RubyGems is unable to load or activate a gem. Contains the
diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb
index 2ced9ccdfb..86821a9f57 100644
--- a/lib/rubygems/version.rb
+++ b/lib/rubygems/version.rb
@@ -145,8 +145,8 @@ class Gem::Version
include Comparable
- VERSION_PATTERN = '[0-9]+(\.[0-9a-zA-Z]+)*' # :nodoc:
- ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})*\s*\z/ # :nodoc:
+ VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*' # :nodoc:
+ ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/ # :nodoc:
##
# A string representation of this Version.
diff --git a/lib/tempfile.rb b/lib/tempfile.rb
index b34251ebb6..a34e178edb 100644
--- a/lib/tempfile.rb
+++ b/lib/tempfile.rb
@@ -190,7 +190,6 @@ class Tempfile < DelegateClass(File)
def close!
_close
unlink
- ObjectSpace.undefine_finalizer(self)
end
# Unlinks (deletes) the file from the filesystem. One should always unlink
@@ -238,6 +237,7 @@ class Tempfile < DelegateClass(File)
# remove tmpname from remover
@data[0] = @data[1] = nil
@tmpname = nil
+ ObjectSpace.undefine_finalizer(self)
end
alias delete unlink
diff --git a/lib/thread.rb b/lib/thread.rb
index 58c4f6b9e6..494a5b33e4 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -355,6 +355,22 @@ class SizedQueue < Queue
def num_waiting
@waiting.size + @queue_wait.size
end
+
+ #
+ # Removes all objects from the queue and wakes waiting threads, if any.
+ #
+ def clear
+ @mutex.synchronize do
+ @que.clear
+ begin
+ until @queue_wait.empty?
+ @queue_wait.shift.wakeup
+ end
+ rescue ThreadError
+ retry
+ end
+ end
+ end
end
# Documentation comments:
diff --git a/lib/time.rb b/lib/time.rb
index 1663af8e76..40b28d9085 100644
--- a/lib/time.rb
+++ b/lib/time.rb
@@ -282,7 +282,11 @@ class Time
d = Date._strptime(date, format)
raise ArgumentError, "invalid strptime format - `#{format}'" unless d
if seconds = d[:seconds]
- Time.at(seconds)
+ if offset = d[:offset]
+ Time.at(seconds).localtime(offset)
+ else
+ Time.at(seconds)
+ end
else
year = d[:year]
year = yield(year) if year && block_given?
diff --git a/lib/webrick/htmlutils.rb b/lib/webrick/htmlutils.rb
index ed901f1ce2..90994f18b8 100644
--- a/lib/webrick/htmlutils.rb
+++ b/lib/webrick/htmlutils.rb
@@ -15,12 +15,13 @@ module WEBrick
# Escapes &, ", > and < in +string+
def escape(string)
- str = string ? string.dup : ""
+ return "" unless string
+ str = string.dup.force_encoding('binary')
str.gsub!(/&/n, '&amp;')
str.gsub!(/\"/n, '&quot;')
str.gsub!(/>/n, '&gt;')
str.gsub!(/</n, '&lt;')
- str
+ str.force_encoding(string.encoding)
end
module_function :escape
diff --git a/lib/webrick/httputils.rb b/lib/webrick/httputils.rb
index f029dacb56..d99573762c 100644
--- a/lib/webrick/httputils.rb
+++ b/lib/webrick/httputils.rb
@@ -350,8 +350,18 @@ module WEBrick
def _make_regex(str) /([#{Regexp.escape(str)}])/n end
def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end
- def _escape(str, regex) str.gsub(regex){ "%%%02X" % $1.ord } end
- def _unescape(str, regex) str.gsub(regex){ $1.hex.chr } end
+ def _escape(str, regex)
+ str = str.dup.force_encoding('binary')
+ str.gsub!(regex) {"%%%02X" % $1.ord}
+ # %-escaped string should contain US-ASCII only
+ str.force_encoding(Encoding::US_ASCII)
+ end
+ def _unescape(str, regex)
+ str = str.dup.force_encoding('binary')
+ str.gsub!(regex) {$1.hex.chr}
+ # encoding of %-unescaped string is unknown
+ str
+ end
UNESCAPED = _make_regex(control+space+delims+unwise+nonascii)
UNESCAPED_FORM = _make_regex(reserved+control+delims+unwise+nonascii)
diff --git a/lib/yaml.rb b/lib/yaml.rb
index ff9e1a6344..3461f68606 100644
--- a/lib/yaml.rb
+++ b/lib/yaml.rb
@@ -1,18 +1,46 @@
-##
-# The YAML module allows you to use one of the two YAML engines that ship with
-# ruby. By default Psych is used but the old and unmaintained Syck may be
-# chosen.
+# YAML Ain't Markup Language
#
-# See Psych or Syck for usage and documentation.
+# This module provides a Ruby interface for data serialization in YAML format.
#
-# To set the YAML engine to syck:
+# You can choose from one of two YAML engines that ship with Ruby 1.9. By
+# default Psych is used but the old unmaintained Syck may chosen.
#
-# YAML::ENGINE.yamler = 'syck'
+# == Usage
+#
+# Working with YAML can be very simple, for example:
+#
+# require 'yaml' # STEP ONE, REQUIRE YAML!
+# # Parse a YAML string
+# YAML.load("--- foo") #=> "foo"
+#
+# # Emit some YAML
+# YAML.dump("foo") # => "--- foo\n...\n"
+# { :a => 'b'}.to_yaml # => "---\n:a: b\n"
+#
+# == Security
+#
+# Do not use YAML to load untrusted data. Doing so is unsafe and could allow
+# malicious input to execute arbitrary code inside your application. Please see
+# doc/security.rdoc for more information.
+#
+# == Syck
#
-# To set the YAML engine back to psych:
+# Syck was the original for YAML implementation in Ruby's standard library
+# developed by why the lucky stiff.
#
+# If you prefer, you can still use Syck by changing the YAML::ENGINE like so:
+#
+# YAML::ENGINE.yamler = 'syck'
+# # switch back to the default Psych
# YAML::ENGINE.yamler = 'psych'
-
+#
+# In older Ruby versions, ie. <= 1.9, Syck is still provided, however it was
+# completely removed with the release of Ruby 2.0.0.
+#
+# == More info
+#
+# For more advanced details on the implementation see Psych, and also check out
+# http://yaml.org for spec details and other helpful information.
module YAML
class EngineManager # :nodoc:
attr_reader :yamler
@@ -45,7 +73,7 @@ module YAML
##
# Allows changing the current YAML engine. See YAML for details.
- ENGINE = YAML::EngineManager.new
+ ENGINE = YAML::EngineManager.new # :nodoc:
end
if defined?(Psych)
@@ -65,11 +93,11 @@ else
end
end
-module Syck
+module Syck # :nodoc:
ENGINE = YAML::ENGINE
end
-module Psych
+module Psych # :nodoc:
ENGINE = YAML::ENGINE
end
diff --git a/node.h b/node.h
index bb96107711..a15e15781b 100644
--- a/node.h
+++ b/node.h
@@ -447,6 +447,7 @@ typedef struct RNode {
#define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a)
#define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0)
#define NEW_OPTBLOCK(a) NEW_NODE(NODE_OPTBLOCK,a,0,0)
+#define NEW_MEMO(a,b,c) NEW_NODE(NODE_MEMO,a,b,c)
#if defined __GNUC__ && __GNUC__ >= 4
#pragma GCC visibility push(default)
diff --git a/numeric.c b/numeric.c
index 56f08bc237..e78c9c403d 100644
--- a/numeric.c
+++ b/numeric.c
@@ -2173,8 +2173,8 @@ fix_succ(VALUE num)
* (-1).next #=> 0
*/
-static VALUE
-int_succ(VALUE num)
+VALUE
+rb_int_succ(VALUE num)
{
if (FIXNUM_P(num)) {
long i = FIX2LONG(num) + 1;
@@ -2183,6 +2183,8 @@ int_succ(VALUE num)
return rb_funcall(num, '+', 1, INT2FIX(1));
}
+#define int_succ rb_int_succ
+
/*
* call-seq:
* int.pred -> integer
@@ -2193,8 +2195,8 @@ int_succ(VALUE num)
* (-1).pred #=> -2
*/
-static VALUE
-int_pred(VALUE num)
+VALUE
+rb_int_pred(VALUE num)
{
if (FIXNUM_P(num)) {
long i = FIX2LONG(num) - 1;
@@ -2203,6 +2205,8 @@ int_pred(VALUE num)
return rb_funcall(num, '-', 1, INT2FIX(1));
}
+#define int_pred rb_int_pred
+
VALUE
rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
{
diff --git a/object.c b/object.c
index 59611fd2d6..1ab28a3587 100644
--- a/object.c
+++ b/object.c
@@ -285,7 +285,7 @@ rb_obj_clone(VALUE obj)
}
clone = rb_obj_alloc(rb_obj_class(obj));
RBASIC(clone)->klass = rb_singleton_class_clone(obj);
- RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) & ~(FL_FREEZE|FL_FINALIZE|FL_MARK);
+ RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) & ~(FL_FREEZE|FL_FINALIZE|FL_MARK) | (RBASIC(clone)->flags&FL_MARK);
init_copy(clone, obj);
rb_funcall(clone, id_init_clone, 1, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
@@ -1234,7 +1234,8 @@ rb_obj_not_match(VALUE obj1, VALUE obj2)
* call-seq:
* obj <=> other -> 0 or nil
*
- * Returns 0 if obj === other, otherwise nil.
+ * Returns 0 if +obj+ and +other+ are the same object
+ * or <code>obj == other</code>, otherwise nil.
*/
static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
diff --git a/parse.y b/parse.y
index 3f05fd5b6b..7afa762b4b 100644
--- a/parse.y
+++ b/parse.y
@@ -102,6 +102,7 @@ struct local_vars {
struct vtable *vars;
struct vtable *used;
struct local_vars *prev;
+ stack_type cmdargs;
};
#define DVARS_INHERIT ((void*)1)
@@ -277,8 +278,6 @@ struct parser_params {
static int parser_yyerror(struct parser_params*, const char*);
#define yyerror(msg) parser_yyerror(parser, (msg))
-#define YYLEX_PARAM parser
-
#define lex_strterm (parser->parser_lex_strterm)
#define lex_state (parser->parser_lex_state)
#define cond_stack (parser->parser_cond_stack)
@@ -319,7 +318,11 @@ static int parser_yyerror(struct parser_params*, const char*);
#define ruby_coverage (parser->coverage)
#endif
+#if YYPURE
static int yylex(void*, void*);
+#else
+static int yylex(void*);
+#endif
#ifndef RIPPER
#define yyparse ruby_yyparse
@@ -610,7 +613,8 @@ static void token_info_pop(struct parser_params*, const char *token);
#endif
%}
-%pure_parser
+%pure-parser
+%lex-param {struct parser_params *parser}
%parse-param {struct parser_params *parser}
%union {
@@ -6004,6 +6008,70 @@ ripper_flush_string_content(struct parser_params *parser, rb_encoding *enc)
#define flush_string_content(enc) ((void)(enc))
#endif
+RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32];
+/* this can be shared with ripper, since it's independent from struct
+ * parser_params. */
+#ifndef RIPPER
+#define BIT(c, idx) (((c) / 32 - 1 == idx) ? (1U << ((c) % 32)) : 0)
+#define SPECIAL_PUNCT(idx) ( \
+ BIT('~', idx) | BIT('*', idx) | BIT('$', idx) | BIT('?', idx) | \
+ BIT('!', idx) | BIT('@', idx) | BIT('/', idx) | BIT('\\', idx) | \
+ BIT(';', idx) | BIT(',', idx) | BIT('.', idx) | BIT('=', idx) | \
+ BIT(':', idx) | BIT('<', idx) | BIT('>', idx) | BIT('\"', idx) | \
+ BIT('&', idx) | BIT('`', idx) | BIT('\'', idx) | BIT('+', idx) | \
+ BIT('0', idx))
+const unsigned int ruby_global_name_punct_bits[] = {
+ SPECIAL_PUNCT(0),
+ SPECIAL_PUNCT(1),
+ SPECIAL_PUNCT(2),
+};
+#undef BIT
+#undef SPECIAL_PUNCT
+#endif
+
+static inline int
+is_global_name_punct(const char c)
+{
+ if (c <= 0x20 || 0x7e < c) return 0;
+ return (ruby_global_name_punct_bits[(c - 0x20) / 32] >> (c % 32)) & 1;
+}
+
+static int
+parser_peek_variable_name(struct parser_params *parser)
+{
+ int c;
+ const char *p = lex_p;
+
+ if (p + 1 >= lex_pend) return 0;
+ c = *p++;
+ switch (c) {
+ case '$':
+ if ((c = *p) == '-') {
+ if (++p >= lex_pend) return 0;
+ c = *p;
+ }
+ else if (is_global_name_punct(c) || ISDIGIT(c)) {
+ return tSTRING_DVAR;
+ }
+ break;
+ case '@':
+ if ((c = *p) == '@') {
+ if (++p >= lex_pend) return 0;
+ c = *p;
+ }
+ break;
+ case '{':
+ lex_p = p;
+ command_start = TRUE;
+ return tSTRING_DBEG;
+ default:
+ return 0;
+ }
+ if (!ISASCII(c) || c == '_' || ISALPHA(c))
+ return tSTRING_DVAR;
+ return 0;
+}
+
static int
parser_parse_string(struct parser_params *parser, NODE *quote)
{
@@ -6034,15 +6102,10 @@ parser_parse_string(struct parser_params *parser, NODE *quote)
}
newtok();
if ((func & STR_FUNC_EXPAND) && c == '#') {
- switch (c = nextc()) {
- case '$':
- case '@':
- pushback(c);
- return tSTRING_DVAR;
- case '{':
- return tSTRING_DBEG;
- }
+ int t = parser_peek_variable_name(parser);
+ if (t) return t;
tokadd('#');
+ c = nextc();
}
pushback(c);
if (tokadd_string(func, term, paren, &quote->nd_nest,
@@ -6249,15 +6312,10 @@ parser_here_document(struct parser_params *parser, NODE *here)
/* int mb = ENC_CODERANGE_7BIT, *mbp = &mb;*/
newtok();
if (c == '#') {
- switch (c = nextc()) {
- case '$':
- case '@':
- pushback(c);
- return tSTRING_DVAR;
- case '{':
- return tSTRING_DBEG;
- }
+ int t = parser_peek_variable_name(parser);
+ if (t) return t;
tokadd('#');
+ c = nextc();
}
do {
pushback(c);
@@ -7743,7 +7801,8 @@ parser_yylex(struct parser_params *parser)
default:
if (!parser_is_identchar()) {
pushback(c);
- return '$';
+ compile_error(PARSER_ARG "`$%c' is not allowed as a global variable name", c);
+ return 0;
}
case '0':
tokadd('$');
@@ -7758,7 +7817,8 @@ parser_yylex(struct parser_params *parser)
tokadd('@');
c = nextc();
}
- if (c != -1 && ISDIGIT(c)) {
+ if (c != -1 && (ISDIGIT(c) || !parser_is_identchar())) {
+ pushback(c);
if (tokidx == 1) {
compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c);
}
@@ -7767,10 +7827,6 @@ parser_yylex(struct parser_params *parser)
}
return 0;
}
- if (!parser_is_identchar()) {
- pushback(c);
- return '@';
- }
break;
case '_':
@@ -9140,6 +9196,8 @@ local_push_gen(struct parser_params *parser, int inherit_dvars)
local->args = vtable_alloc(0);
local->vars = vtable_alloc(inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE);
local->used = !inherit_dvars && RTEST(ruby_verbose) ? vtable_alloc(0) : 0;
+ local->cmdargs = cmdarg_stack;
+ cmdarg_stack = 0;
lvtbl = local;
}
@@ -9153,6 +9211,7 @@ local_pop_gen(struct parser_params *parser)
}
vtable_free(lvtbl->args);
vtable_free(lvtbl->vars);
+ cmdarg_stack = lvtbl->cmdargs;
xfree(lvtbl);
lvtbl = local;
}
@@ -9563,8 +9622,6 @@ static const struct {
} op_tbl[] = {
{tDOT2, ".."},
{tDOT3, "..."},
- {'+', "+(binary)"},
- {'-', "-(binary)"},
{tPOW, "**"},
{tUPLUS, "+@"},
{tUMINUS, "-@"},
@@ -9669,22 +9726,17 @@ is_special_global_name(const char *m, const char *e, rb_encoding *enc)
int mb = 0;
if (m >= e) return 0;
- switch (*m) {
- case '~': case '*': case '$': case '?': case '!': case '@':
- case '/': case '\\': case ';': case ',': case '.': case '=':
- case ':': case '<': case '>': case '\"':
- case '&': case '`': case '\'': case '+':
- case '0':
+ if (is_global_name_punct(*m)) {
++m;
- break;
- case '-':
+ }
+ else if (*m == '-') {
++m;
if (m < e && is_identchar(m, e, enc)) {
if (!ISASCII(*m)) mb = 1;
m += rb_enc_mbclen(m, e, enc);
}
- break;
- default:
+ }
+ else {
if (!rb_enc_isdigit(*m, enc)) return 0;
do {
if (!ISASCII(*m)) mb = 1;
diff --git a/proc.c b/proc.c
index 943a49a96a..ca6d3c4769 100644
--- a/proc.c
+++ b/proc.c
@@ -27,7 +27,7 @@ VALUE rb_cMethod;
VALUE rb_cBinding;
VALUE rb_cProc;
-static VALUE bmcall(VALUE, VALUE);
+static VALUE bmcall(VALUE, VALUE, int, VALUE *, VALUE);
static int method_arity(VALUE);
/* Proc */
@@ -465,6 +465,14 @@ rb_block_proc(void)
return proc_new(rb_cProc, FALSE);
}
+/*
+ * call-seq:
+ * lambda { |...| block } -> a_proc
+ *
+ * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
+ * check the number of parameters passed when called.
+ */
+
VALUE
rb_block_lambda(void)
{
@@ -478,20 +486,6 @@ rb_f_lambda(void)
return rb_block_lambda();
}
-/*
- * call-seq:
- * lambda { |...| block } -> a_proc
- *
- * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
- * check the number of parameters passed when called.
- */
-
-static VALUE
-proc_lambda(void)
-{
- return rb_block_lambda();
-}
-
/* Document-method: ===
*
* call-seq:
@@ -1413,6 +1407,13 @@ method_clone(VALUE self)
VALUE
rb_method_call(int argc, VALUE *argv, VALUE method)
{
+ VALUE proc = rb_block_given_p() ? rb_block_proc() : Qnil;
+ return rb_method_call_with_block(argc, argv, method, proc);
+}
+
+VALUE
+rb_method_call_with_block(int argc, VALUE *argv, VALUE method, VALUE pass_procval)
+{
VALUE result = Qnil; /* OK */
struct METHOD *data;
int state;
@@ -1431,8 +1432,15 @@ rb_method_call(int argc, VALUE *argv, VALUE method)
}
if ((state = EXEC_TAG()) == 0) {
rb_thread_t *th = GET_THREAD();
+ rb_block_t *block = 0;
+
+ if (!NIL_P(pass_procval)) {
+ rb_proc_t *pass_proc;
+ GetProcPtr(pass_procval, pass_proc);
+ block = &pass_proc->block;
+ }
- PASS_PASSED_BLOCK_TH(th);
+ th->passed_block = block;
result = rb_vm_call(th, data->recv, data->id, argc, argv, data->me);
}
POP_TAG();
@@ -1798,21 +1806,20 @@ method_inspect(VALUE method)
static VALUE
mproc(VALUE method)
{
- return rb_funcall(Qnil, rb_intern("proc"), 0);
+ return rb_funcall2(rb_mRubyVMFrozenCore, idProc, 0, 0);
}
static VALUE
mlambda(VALUE method)
{
- return rb_funcall(Qnil, rb_intern("lambda"), 0);
+ return rb_funcall(rb_mRubyVMFrozenCore, idLambda, 0, 0);
}
static VALUE
-bmcall(VALUE args, VALUE method)
+bmcall(VALUE args, VALUE method, int argc, VALUE *argv, VALUE passed_proc)
{
volatile VALUE a;
VALUE ret;
- int argc;
if (CLASS_OF(args) != rb_cArray) {
args = rb_ary_new3(1, args);
@@ -1821,7 +1828,7 @@ bmcall(VALUE args, VALUE method)
else {
argc = check_argc(RARRAY_LEN(args));
}
- ret = rb_method_call(argc, RARRAY_PTR(args), method);
+ ret = rb_method_call_with_block(argc, RARRAY_PTR(args), method, passed_proc);
RB_GC_GUARD(a) = args;
return ret;
}
@@ -2151,7 +2158,7 @@ Init_Proc(void)
/* utility functions */
rb_define_global_function("proc", rb_block_proc, 0);
- rb_define_global_function("lambda", proc_lambda, 0);
+ rb_define_global_function("lambda", rb_block_lambda, 0);
/* Method */
rb_cMethod = rb_define_class("Method", rb_cObject);
diff --git a/process.c b/process.c
index 99cfc69469..0c19d58122 100644
--- a/process.c
+++ b/process.c
@@ -1949,16 +1949,28 @@ redirect_dup(int oldfd)
ttyprintf("dup(%d) => %d\n", oldfd, ret);
return ret;
}
+#else
+#define redirect_dup(oldfd) dup(oldfd)
+#endif
+#if defined(DEBUG_REDIRECT) || defined(_WIN32)
static int
redirect_dup2(int oldfd, int newfd)
{
int ret;
ret = dup2(oldfd, newfd);
+ if (newfd >= 0 && newfd <= 2)
+ SetStdHandle(newfd == 0 ? STD_INPUT_HANDLE : newfd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, (HANDLE)rb_w32_get_osfhandle(newfd));
+#if defined(DEBUG_REDIRECT)
ttyprintf("dup2(%d, %d)\n", oldfd, newfd);
+#endif
return ret;
}
+#else
+#define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
+#endif
+#if defined(DEBUG_REDIRECT)
static int
redirect_close(int fd)
{
@@ -1978,8 +1990,6 @@ redirect_open(const char *pathname, int flags, mode_t perm)
}
#else
-#define redirect_dup(oldfd) dup(oldfd)
-#define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
#define redirect_close(fd) close(fd)
#define redirect_open(pathname, flags, perm) open((pathname), (flags), (perm))
#endif
@@ -4905,29 +4915,23 @@ rb_daemon(int nochdir, int noclose)
before_fork();
err = daemon(nochdir, noclose);
after_fork();
+ rb_thread_atfork();
#else
int n;
- switch (rb_fork(0, 0, 0, Qnil)) {
- case -1:
- rb_sys_fail("daemon");
- case 0:
- break;
- default:
- _exit(EXIT_SUCCESS);
+#define fork_daemon() \
+ switch (rb_fork(0, 0, 0, Qnil)) { \
+ case -1: return -1; \
+ case 0: rb_thread_atfork(); break; \
+ default: _exit(EXIT_SUCCESS); \
}
- proc_setsid();
+ fork_daemon();
+
+ if (setsid() < 0) return -1;
/* must not be process-leader */
- switch (rb_fork(0, 0, 0, Qnil)) {
- case -1:
- return -1;
- case 0:
- break;
- default:
- _exit(EXIT_SUCCESS);
- }
+ fork_daemon();
if (!nochdir)
err = chdir("/");
diff --git a/rational.c b/rational.c
index 8aced2aee8..c66b998506 100644
--- a/rational.c
+++ b/rational.c
@@ -1230,6 +1230,10 @@ f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
b = f_expt10(n);
s = f_mul(self, b);
+ if (!k_rational_p(s)) {
+ s = f_rational_new_bang1(CLASS_OF(self), s);
+ }
+
s = (*func)(s);
s = f_div(f_rational_new_bang1(CLASS_OF(self), s), b);
diff --git a/regexec.c b/regexec.c
index 55c28178c4..33b4a4efa6 100644
--- a/regexec.c
+++ b/regexec.c
@@ -3515,15 +3515,14 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
start = min_semi_end - reg->anchor_dmax;
if (start < end)
start = onigenc_get_right_adjust_char_head(reg->enc, str, start, end);
- else { /* match with empty at end */
- start = onigenc_get_prev_char_head(reg->enc, str, end, end);
- }
}
if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {
range = max_semi_end - reg->anchor_dmin + 1;
}
- if (start >= range) goto mismatch_no_msa;
+ if (start > range) goto mismatch_no_msa;
+ /* If start == range, match with empty at end.
+ Backward search is used. */
}
else {
if ((OnigDistance )(min_semi_end - range) > reg->anchor_dmax) {
diff --git a/ruby_atomic.h b/ruby_atomic.h
index f4dd5db38a..df1c10da8c 100644
--- a/ruby_atomic.h
+++ b/ruby_atomic.h
@@ -3,6 +3,30 @@
#if 0
#elif defined HAVE_GCC_ATOMIC_BUILTINS
+typedef unsigned int rb_atomic_t;
+# define ATOMIC_SET(var, val) (void)__atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST)
+# define ATOMIC_INC(var) __atomic_fetch_add(&(var), 1, __ATOMIC_SEQ_CST)
+# define ATOMIC_DEC(var) __atomic_fetch_sub(&(var), 1, __ATOMIC_SEQ_CST)
+# define ATOMIC_OR(var, val) __atomic_or_fetch(&(var), (val), __ATOMIC_SEQ_CST)
+# define ATOMIC_EXCHANGE(var, val) __atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST)
+# define ATOMIC_CAS(var, oldval, newval) \
+({ __typeof__(oldval) oldvaldup = (oldval); /* oldval should not be modified */ \
+ __atomic_compare_exchange_n(&(var), &oldvaldup, (newval), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \
+ oldvaldup; })
+
+# define ATOMIC_SIZE_ADD(var, val) __atomic_fetch_add(&(var), (val), __ATOMIC_SEQ_CST)
+# define ATOMIC_SIZE_SUB(var, val) __atomic_fetch_sub(&(var), (val), __ATOMIC_SEQ_CST)
+# define ATOMIC_SIZE_INC(var) __atomic_fetch_add(&(var), 1, __ATOMIC_SEQ_CST)
+# define ATOMIC_SIZE_DEC(var) __atomic_fetch_sub(&(var), 1, __ATOMIC_SEQ_CST)
+# define ATOMIC_SIZE_EXCHANGE(var, val) __atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST)
+# define ATOMIC_SIZE_CAS(var, oldval, newval) \
+({ size_t oldvaldup = (oldval); \
+ __atomic_compare_exchange_n(&(var), &oldvaldup, (newval), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \
+ oldvaldup; })
+
+# define ATOMIC_PTR_EXCHANGE(var, val) __atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST)
+
+#elif defined HAVE_GCC_SYNC_BUILTINS
/* @shyouhei hack to support atomic operations in case of gcc. Gcc
* has its own pseudo-insns to support them. See info, or
* http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html */
@@ -13,12 +37,16 @@ typedef unsigned int rb_atomic_t; /* Anything OK */
# define ATOMIC_DEC(var) __sync_fetch_and_sub(&(var), 1)
# define ATOMIC_OR(var, val) __sync_or_and_fetch(&(var), (val))
# define ATOMIC_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val))
+# define ATOMIC_CAS(var, oldval, newval) __sync_val_compare_and_swap(&(var), (oldval), (newval))
# define ATOMIC_SIZE_ADD(var, val) __sync_fetch_and_add(&(var), (val))
# define ATOMIC_SIZE_SUB(var, val) __sync_fetch_and_sub(&(var), (val))
# define ATOMIC_SIZE_INC(var) __sync_fetch_and_add(&(var), 1)
# define ATOMIC_SIZE_DEC(var) __sync_fetch_and_sub(&(var), 1)
# define ATOMIC_SIZE_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val))
+# define ATOMIC_PTR_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val))
+
+# define ATOMIC_PTR_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val))
#elif defined _WIN32
#if defined _MSC_VER && _MSC_VER > 1200
@@ -48,13 +76,24 @@ rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val)
# define ATOMIC_OR(var, val) _InterlockedOr(&(var), (val))
#endif
# define ATOMIC_EXCHANGE(var, val) InterlockedExchange(&(var), (val))
+# define ATOMIC_CAS(var, oldval, newval) InterlockedCompareExchange(&(var), (newval), (oldval))
+# if defined _MSC_VER && _MSC_VER <= 1200
+static inline rb_atomic_t
+rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval)
+{
+ return (rb_atomic_t)InterlockedCompareExchange((PVOID *)var, (PVOID)newval, (PVOID)oldval);
+}
+# undef ATOMIC_CAS
+# define ATOMIC_CAS(var, oldval, newval) rb_w32_atomic_cas(&(var), (oldval), (newval))
+# endif
# ifdef _M_AMD64
# define ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd64(&(var), (val))
# define ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd64(&(var), -(val))
# define ATOMIC_SIZE_INC(var) InterlockedIncrement64(&(var))
# define ATOMIC_SIZE_DEC(var) InterlockedDecrement64(&(var))
# define ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange64(&(var), (val))
+# define ATOMIC_SIZE_CAS(var, oldval, val) InterlockedCompareExchange64(&(var), (oldval), (val))
# else
# define ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd((LONG *)&(var), (val))
# define ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd((LONG *)&(var), -(val))
@@ -63,7 +102,7 @@ rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val)
# define ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange((LONG *)&(var), (val))
# endif
-#elif defined(__sun)
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
#include <atomic.h>
typedef unsigned int rb_atomic_t;
@@ -72,6 +111,7 @@ typedef unsigned int rb_atomic_t;
# define ATOMIC_DEC(var) atomic_dec_uint(&(var))
# define ATOMIC_OR(var, val) atomic_or_uint(&(var), (val))
# define ATOMIC_EXCHANGE(var, val) atomic_swap_uint(&(var), (val))
+# define ATOMIC_CAS(var, oldval, newval) atomic_cas_uint(&(var), (oldval), (newval))
# if SIZEOF_SIZE_T == SIZEOF_LONG
# define ATOMIC_SIZE_ADD(var, val) atomic_add_long(&(var), (val))
@@ -79,6 +119,7 @@ typedef unsigned int rb_atomic_t;
# define ATOMIC_SIZE_INC(var) atomic_inc_ulong(&(var))
# define ATOMIC_SIZE_DEC(var) atomic_dec_ulong(&(var))
# define ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_ulong(&(var), (val))
+# define ATOMIC_SIZE_CAS(var, oldval, val) atomic_cas_ulong(&(var), (oldval), (val))
# else
# define ATOMIC_SIZE_ADD(var, val) atomic_add_int(&(var), (val))
# define ATOMIC_SIZE_SUB(var, val) atomic_add_int(&(var), -(val))
@@ -91,12 +132,16 @@ typedef unsigned int rb_atomic_t;
typedef int rb_atomic_t;
#define NEED_RUBY_ATOMIC_EXCHANGE
extern rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val);
+extern rb_atomic_t ruby_atomic_compare_and_swap(rb_atomic_t *ptr,
+ rb_atomic_t cmp,
+ rb_atomic_t newval);
# define ATOMIC_SET(var, val) (void)((var) = (val))
# define ATOMIC_INC(var) ((var)++)
# define ATOMIC_DEC(var) ((var)--)
# define ATOMIC_OR(var, val) ((var) |= (val))
# define ATOMIC_EXCHANGE(var, val) ruby_atomic_exchange(&(var), (val))
+# define ATOMIC_CAS(var, oldval, newval) ruby_atomic_compare_and_swap(&(var), (oldval), (newval))
# define ATOMIC_SIZE_ADD(var, val) (void)((var) += (val))
# define ATOMIC_SIZE_SUB(var, val) (void)((var) -= (val))
@@ -112,4 +157,19 @@ atomic_size_exchange(size_t *ptr, size_t val)
}
#endif
+#ifndef ATOMIC_SIZE_CAS
+# define ATOMIC_SIZE_CAS(var, oldval, val) ATOMIC_CAS(var, oldval, val)
+#endif
+
+#ifndef ATOMIC_PTR_EXCHANGE
+# if SIZEOF_VOIDP == SIZEOF_SIZE_T
+# define ATOMIC_PTR_EXCHANGE(var, val) (void *)ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val))
+# endif
+#endif
+#ifndef ATOMIC_PTR_CAS
+# if SIZEOF_VOIDP == SIZEOF_SIZE_T
+# define ATOMIC_PTR_CAS(var, oldval, val) (void *)ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val))
+# endif
+#endif
+
#endif /* RUBY_ATOMIC_H */
diff --git a/signal.c b/signal.c
index 0588d9696c..2e920f9f76 100644
--- a/signal.c
+++ b/signal.c
@@ -18,6 +18,9 @@
#include <errno.h>
#include <unistd.h>
#include "ruby_atomic.h"
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
#if !defined(_WIN32) && !defined(HAVE_GCC_ATOMIC_BUILTINS)
rb_atomic_t
@@ -27,6 +30,17 @@ ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
*ptr = val;
return old;
}
+
+rb_atomic_t
+ruby_atomic_compare_and_swap(rb_atomic_t *ptr, rb_atomic_t cmp,
+ rb_atomic_t newval)
+{
+ rb_atomic_t old = *ptr;
+ if (old == cmp) {
+ *ptr = newval;
+ }
+ return old;
+}
#endif
#if defined(__BEOS__) || defined(__HAIKU__)
diff --git a/st.c b/st.c
index c093bfd392..8c238c33f8 100644
--- a/st.c
+++ b/st.c
@@ -695,6 +695,45 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val
return 0;
}
+int
+st_shift(register st_table *table, register st_data_t *key, st_data_t *value)
+{
+ st_index_t hash_val;
+ st_table_entry **prev;
+ register st_table_entry *ptr;
+
+ if (table->num_entries == 0) {
+ if (value != 0) *value = 0;
+ return 0;
+ }
+
+ if (table->entries_packed) {
+ if (value != 0) *value = (st_data_t)table->bins[1];
+ *key = (st_data_t)table->bins[0];
+ table->num_entries--;
+ memmove(&table->bins[0], &table->bins[2],
+ sizeof(struct st_table_entry*) * 2*table->num_entries);
+ return 1;
+ }
+
+ hash_val = do_hash_bin(table->head->key, table);
+ prev = &table->bins[hash_val];
+ for (;(ptr = *prev) != 0; prev = &ptr->next) {
+ if (ptr == table->head) {
+ *prev = ptr->next;
+ REMOVE_ENTRY(table, ptr);
+ if (value != 0) *value = ptr->record;
+ *key = ptr->key;
+ free(ptr);
+ return 1;
+ }
+ }
+
+ /* if hash is not consistent and need to be rehashed */
+ if (value != 0) *value = 0;
+ return 0;
+}
+
void
st_cleanup_safe(st_table *table, st_data_t never)
{
diff --git a/string.c b/string.c
index f2c60715a2..8f692b41af 100644
--- a/string.c
+++ b/string.c
@@ -1337,6 +1337,7 @@ rb_str_modify_expand(VALUE str, long expand)
long capa = len + expand;
if (!STR_EMBED_P(str)) {
REALLOC_N(RSTRING(str)->as.heap.ptr, char, capa+1);
+ STR_UNSET_NOCAPA(str);
RSTRING(str)->as.heap.aux.capa = capa;
}
else if (capa > RSTRING_EMBED_LEN_MAX) {
@@ -1751,6 +1752,13 @@ rb_str_unlocktmp(VALUE str)
return str;
}
+VALUE
+rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg)
+{
+ rb_str_locktmp(str);
+ return rb_ensure(func, arg, rb_str_unlocktmp, str);
+}
+
void
rb_str_set_len(VALUE str, long len)
{
@@ -7512,7 +7520,7 @@ sym_to_sym(VALUE sym)
}
static VALUE
-sym_call(VALUE args, VALUE sym, int argc, VALUE *argv)
+sym_call(VALUE args, VALUE sym, int argc, VALUE *argv, VALUE passed_proc)
{
VALUE obj;
@@ -7520,7 +7528,7 @@ sym_call(VALUE args, VALUE sym, int argc, VALUE *argv)
rb_raise(rb_eArgError, "no receiver given");
}
obj = argv[0];
- return rb_funcall_passing_block(obj, (ID)sym, argc - 1, argv + 1);
+ return rb_funcall_with_block(obj, (ID)sym, argc - 1, argv + 1, passed_proc);
}
/*
diff --git a/template/id.h.tmpl b/template/id.h.tmpl
index 5ad91452ec..ae30cf98a0 100644
--- a/template/id.h.tmpl
+++ b/template/id.h.tmpl
@@ -98,6 +98,7 @@ enum ruby_method_ids {
tGets,
tSucc,
tEach,
+ tProc,
tLambda,
tSend,
t__send__,
@@ -120,6 +121,7 @@ enum ruby_method_ids {
TOKEN2ID(Gets),
TOKEN2ID(Succ),
TOKEN2ID(Each),
+ TOKEN2ID(Proc),
TOKEN2ID(Lambda),
TOKEN2ID(Send),
TOKEN2ID(__send__),
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index 055b0ff4f0..02467937e5 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -1210,11 +1210,35 @@ class TestBigDecimal < Test::Unit::TestCase
end
def test_BigMath_exp
- n = 20
- assert_in_epsilon(Math.exp(n), BigMath.exp(BigDecimal("20"), n))
- assert_in_epsilon(Math.exp(40), BigMath.exp(BigDecimal("40"), n))
- assert_in_epsilon(Math.exp(-n), BigMath.exp(BigDecimal("-20"), n))
- assert_in_epsilon(Math.exp(-40), BigMath.exp(BigDecimal("-40"), n))
+ prec = 20
+ assert_in_epsilon(Math.exp(20), BigMath.exp(BigDecimal("20"), prec))
+ assert_in_epsilon(Math.exp(40), BigMath.exp(BigDecimal("40"), prec))
+ assert_in_epsilon(Math.exp(-20), BigMath.exp(BigDecimal("-20"), prec))
+ assert_in_epsilon(Math.exp(-40), BigMath.exp(BigDecimal("-40"), prec))
+ end
+
+ def test_BigMath_exp_with_float
+ prec = 20
+ assert_in_epsilon(Math.exp(20), BigMath.exp(20.0, prec))
+ assert_in_epsilon(Math.exp(40), BigMath.exp(40.0, prec))
+ assert_in_epsilon(Math.exp(-20), BigMath.exp(-20.0, prec))
+ assert_in_epsilon(Math.exp(-40), BigMath.exp(-40.0, prec))
+ end
+
+ def test_BigMath_exp_with_fixnum
+ prec = 20
+ assert_in_epsilon(Math.exp(20), BigMath.exp(20, prec))
+ assert_in_epsilon(Math.exp(40), BigMath.exp(40, prec))
+ assert_in_epsilon(Math.exp(-20), BigMath.exp(-20, prec))
+ assert_in_epsilon(Math.exp(-40), BigMath.exp(-40, prec))
+ end
+
+ def test_BigMath_exp_with_rational
+ prec = 20
+ assert_in_epsilon(Math.exp(20), BigMath.exp(Rational(40,2), prec))
+ assert_in_epsilon(Math.exp(40), BigMath.exp(Rational(80,2), prec))
+ assert_in_epsilon(Math.exp(-20), BigMath.exp(Rational(-40,2), prec))
+ assert_in_epsilon(Math.exp(-40), BigMath.exp(Rational(-80,2), prec))
end
def test_BigMath_exp_under_gc_stress
diff --git a/test/coverage/test_coverage.rb b/test/coverage/test_coverage.rb
index 4d785c3c0e..f4f192a578 100644
--- a/test/coverage/test_coverage.rb
+++ b/test/coverage/test_coverage.rb
@@ -47,7 +47,7 @@ class TestCoverage < Test::Unit::TestCase
Dir.mktmpdir {|tmp|
Dir.chdir(tmp) {
File.open("test.rb", "w") do |f|
- f.puts "p\n" * 10000
+ f.puts "__id__\n" * 10000
f.puts "def ignore(x); end"
f.puts "ignore([1"
f.puts "])"
diff --git a/test/date/test_date_parse.rb b/test/date/test_date_parse.rb
index 1504473938..fc77ebc4ac 100644
--- a/test/date/test_date_parse.rb
+++ b/test/date/test_date_parse.rb
@@ -1028,10 +1028,16 @@ class TestDateParse < Test::Unit::TestCase
d = Date.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700', Date::ITALY + 10)
assert_equal(Date.new(2001,2,3), d)
assert_equal(Date::ITALY + 10, d.start)
+ d = Date.rfc2822('3 Feb 2001 04:05:06 +0700', Date::ITALY + 10)
+ assert_equal(Date.new(2001,2,3), d)
+ assert_equal(Date::ITALY + 10, d.start)
d = DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700', Date::ITALY + 10)
assert_equal(DateTime.new(2001,2,3,4,5,6,'+07:00'), d)
assert_equal(Date::ITALY + 10, d.start)
+ d = DateTime.rfc2822('3 Feb 2001 04:05:06 +0700', Date::ITALY + 10)
+ assert_equal(DateTime.new(2001,2,3,4,5,6,'+07:00'), d)
+ assert_equal(Date::ITALY + 10, d.start)
end
def test_httpdate
diff --git a/test/date/test_switch_hitter.rb b/test/date/test_switch_hitter.rb
index 8431d40a29..2a36792f56 100644
--- a/test/date/test_switch_hitter.rb
+++ b/test/date/test_switch_hitter.rb
@@ -294,6 +294,8 @@ class TestSH < Test::Unit::TestCase
assert_raise(Errno::ERANGE) do
Date.new(1 << 10000).strftime('%Y')
end
+ assert_equal('-3786825600', Date.new(1850).strftime('%s'))
+ assert_equal('-3786825600000', Date.new(1850).strftime('%Q'))
end
def test_cmp
@@ -472,6 +474,59 @@ class TestSH < Test::Unit::TestCase
period2_iter(+cm_period * (1 << 64) - 3, +cm_period * (1 << 64) + 3)
end
+ def test_different_alignments
+ assert_equal(0, Date.jd(0) <=> Date.civil(-4713, 11, 24, Date::GREGORIAN))
+ assert_equal(0, Date.jd(213447717) <=> Date.civil(579687, 11, 24))
+ assert_equal(0, Date.jd(-213447717) <=> Date.civil(-589113, 11, 24, Date::GREGORIAN))
+
+ assert_equal(0, Date.jd(0) <=> DateTime.civil(-4713, 11, 24, 0, 0, 0, 0, Date::GREGORIAN))
+ assert_equal(0, Date.jd(213447717) <=> DateTime.civil(579687, 11, 24))
+ assert_equal(0, Date.jd(-213447717) <=> DateTime.civil(-589113, 11, 24, 0, 0, 0, 0, Date::GREGORIAN))
+
+ assert(Date.jd(0) == Date.civil(-4713, 11, 24, Date::GREGORIAN))
+ assert(Date.jd(213447717) == Date.civil(579687, 11, 24))
+ assert(Date.jd(-213447717) == Date.civil(-589113, 11, 24, Date::GREGORIAN))
+
+ assert(Date.jd(0) == DateTime.civil(-4713, 11, 24, 0, 0, 0, 0, Date::GREGORIAN))
+ assert(Date.jd(213447717) == DateTime.civil(579687, 11, 24))
+ assert(Date.jd(-213447717) == DateTime.civil(-589113, 11, 24, 0, 0, 0, 0, Date::GREGORIAN))
+
+ assert(Date.jd(0) === Date.civil(-4713, 11, 24, Date::GREGORIAN))
+ assert(Date.jd(213447717) === Date.civil(579687, 11, 24))
+ assert(Date.jd(-213447717) === Date.civil(-589113, 11, 24, Date::GREGORIAN))
+
+ assert(Date.jd(0) === DateTime.civil(-4713, 11, 24, 12, 0, 0, 0, Date::GREGORIAN))
+ assert(Date.jd(213447717) === DateTime.civil(579687, 11, 24, 12))
+ assert(Date.jd(-213447717) === DateTime.civil(-589113, 11, 24, 12, 0, 0, 0, Date::GREGORIAN))
+
+ a = Date.jd(0)
+ b = Date.civil(-4713, 11, 24, Date::GREGORIAN)
+ assert_equal(0, a <=> b)
+
+ a = Date.civil(-4712, 1, 1, Date::JULIAN)
+ b = Date.civil(-4713, 11, 24, Date::GREGORIAN)
+ a.jd; b.jd
+ assert_equal(0, a <=> b)
+
+ a = Date.jd(0)
+ b = Date.civil(-4713, 11, 24, Date::GREGORIAN)
+ assert(a == b)
+
+ a = Date.civil(-4712, 1, 1, Date::JULIAN)
+ b = Date.civil(-4713, 11, 24, Date::GREGORIAN)
+ a.jd; b.jd
+ assert(a == b)
+
+ a = Date.jd(0)
+ b = Date.civil(-4713, 11, 24, Date::GREGORIAN)
+ assert(a === b)
+
+ a = Date.civil(-4712, 1, 1, Date::JULIAN)
+ b = Date.civil(-4713, 11, 24, Date::GREGORIAN)
+ a.jd; b.jd
+ assert(a === b)
+ end
+
def test_marshal
s = "\x04\bU:\tDate[\bU:\rRational[\ai\x03\xCF\xD3Ji\ai\x00o:\x13Date::Infinity\x06:\a@di\xFA"
d = Marshal.load(s)
diff --git a/test/dl/test_base.rb b/test/dl/test_base.rb
index 0642f0ed89..63dee050d9 100644
--- a/test/dl/test_base.rb
+++ b/test/dl/test_base.rb
@@ -32,6 +32,9 @@ when /darwin/
when /kfreebsd/
libc_so = "/lib/libc.so.0.1"
libm_so = "/lib/libm.so.1"
+when /gnu/ #GNU/Hurd
+ libc_so = "/lib/libc.so.0.3"
+ libm_so = "/lib/libm.so.6"
when /bsd|dragonfly/
libc_so = "/usr/lib/libc.so"
libm_so = "/usr/lib/libm.so"
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb
index ad69f55e69..9a46709693 100644
--- a/test/fiddle/helper.rb
+++ b/test/fiddle/helper.rb
@@ -38,6 +38,9 @@ when /kfreebsd/
when /bsd|dragonfly/
libc_so = "/usr/lib/libc.so"
libm_so = "/usr/lib/libm.so"
+when /gnu/ #GNU/Hurd
+ libc_so = "/lib/libc.so.0.3"
+ libm_so = "/lib/libm.so.6"
when /solaris/
libdir = '/lib'
case [0].pack('L!').size
diff --git a/test/mkmf/test_framework.rb b/test/mkmf/test_framework.rb
new file mode 100644
index 0000000000..48e8bf7213
--- /dev/null
+++ b/test/mkmf/test_framework.rb
@@ -0,0 +1,46 @@
+require_relative 'base'
+
+class TestMkmf
+ class TestHaveFramework < TestMkmf
+ def create_framework(fw, hdrname = "#{fw}.h")
+ Dir.mktmpdir("frameworks") do |dir|
+ fwdir = "#{dir}/#{fw}.framework"
+ hdrdir = "#{fwdir}/Headers"
+ FileUtils.mkdir_p(hdrdir)
+ File.write("#{hdrdir}/#{hdrname}", "")
+ src = "#{fwdir}/main.c"
+ File.write(src, "void #{fw}(void) {}")
+ cmd = LINK_SO.dup
+ RbConfig.expand(cmd, RbConfig::CONFIG.merge("OBJS"=>src))
+ cmd.gsub!("$@", "#{fwdir}/#{fw}")
+ cmd.gsub!(/ -bundle /, ' -dynamiclib ')
+ assert(xsystem(cmd), MKMFLOG)
+ $INCFLAGS << " " << "-F#{dir}".quote
+ yield fw, hdrname
+ end
+ end
+
+ def test_core_foundation_framework
+ assert(have_framework("CoreFoundation"), mkmflog("try as Objective-C"))
+ end
+
+ def test_multi_frameworks
+ assert(have_framework("CoreFoundation"), mkmflog("try as Objective-C"))
+ assert(have_framework("Cocoa"), mkmflog("try as Objective-C"))
+ end
+
+ def test_empty_framework
+ create_framework("MkmfTest") do |fw|
+ assert(have_framework(fw), MKMFLOG)
+ end
+ end
+
+ def test_different_name_header
+ bug8593 = '[ruby-core:55745] [Bug #8593]'
+ create_framework("MkmfTest", "test_mkmf.h") do |fw, hdrname|
+ assert(!have_framework(fw), MKMFLOG)
+ assert(have_framework([fw, hdrname]), MKMFLOG)
+ end
+ end
+ end
+end if /darwin/ =~ RUBY_PLATFORM
diff --git a/test/net/imap/Makefile b/test/net/imap/Makefile
new file mode 100644
index 0000000000..b2bc9c7368
--- /dev/null
+++ b/test/net/imap/Makefile
@@ -0,0 +1,15 @@
+all:
+
+regen_certs:
+ touch server.key
+ make server.crt
+
+cacert.pem: server.key
+ openssl req -new -x509 -days 1825 -key server.key -out cacert.pem -text -subj "/C=JP/ST=Shimane/L=Matz-e city/O=Ruby Core Team/CN=Ruby Test CA/emailAddress=security@ruby-lang.org"
+
+server.csr:
+ openssl req -new -key server.key -out server.csr -text -subj "/C=JP/ST=Shimane/O=Ruby Core Team/OU=Ruby Test/CN=localhost"
+
+server.crt: server.csr cacert.pem
+ openssl x509 -days 1825 -CA cacert.pem -CAkey server.key -set_serial 00 -in server.csr -req -text -out server.crt
+ rm server.csr
diff --git a/test/net/imap/cacert.pem b/test/net/imap/cacert.pem
index bd7e68ac95..7073387877 100644
--- a/test/net/imap/cacert.pem
+++ b/test/net/imap/cacert.pem
@@ -2,59 +2,65 @@ Certificate:
Data:
Version: 3 (0x2)
Serial Number:
- 9f:dc:f7:94:98:05:43:4c
+ b9:90:a2:bf:62:69:17:9c
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=JP, ST=Shimane, L=Matz-e city, O=Ruby Core Team, CN=Ruby Test CA/emailAddress=security@ruby-lang.org
Validity
- Not Before: Dec 23 10:21:33 2010 GMT
- Not After : Jan 1 10:21:33 2014 GMT
+ Not Before: Jan 3 01:34:17 2014 GMT
+ Not After : Jan 2 01:34:17 2019 GMT
Subject: C=JP, ST=Shimane, L=Matz-e city, O=Ruby Core Team, CN=Ruby Test CA/emailAddress=security@ruby-lang.org
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
- Modulus:
- 00:ce:be:2c:9f:47:ba:db:9c:9c:5b:f0:38:3b:f3:
- 74:20:37:76:23:9f:84:1c:81:90:b4:3e:00:20:34:
- 98:7e:81:69:50:a1:c3:65:96:ea:fa:00:da:8c:cc:
- 53:3f:ba:3c:d0:50:7a:5a:b4:6b:ac:d3:2e:18:ca:
- 2a:69:b3:6a:6f:38:c2:32:a8:06:b6:0a:30:a9:ee:
- 03:38:e9:05:a5:19:23:54:a8:3c:b9:08:ad:2b:72:
- 23:df:93:22:c4:46:a8:ea:f1:a6:e9:30:4a:3f:83:
- 39:e9:62:8e:8b:a3:5e:67:89:1d:7c:75:de:05:aa:
- 58:b1:b7:79:7c:10:80:6d:87
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:db:75:d0:45:de:b1:df:bf:71:a0:0e:b0:a5:e6:
+ bc:f4:1c:9d:e5:25:67:64:c5:7b:cb:f1:af:c6:be:
+ 9a:aa:ea:7e:0f:cc:05:af:ef:40:69:06:b2:c9:13:
+ 9d:7e:eb:a2:06:e2:ea:7d:07:c7:c7:99:c7:fb:d5:
+ b8:eb:63:77:62:2b:18:12:c3:53:58:d0:f5:c7:40:
+ 0c:01:d1:26:82:34:16:09:e3:dc:65:f4:dc:bb:5d:
+ a5:41:60:e7:a9:74:ba:d7:4c:b6:a3:9c:c5:8c:89:
+ af:cb:e8:9f:05:fe:ea:fe:64:24:bf:e7:ed:e3:f6:
+ d0:fc:d6:eb:fc:06:82:10:fb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
- 41:C9:49:37:B1:FA:61:E3:BA:D7:19:3D:D9:DA:8C:B9:82:C9:B4:6A
+ E8:7E:58:AC:13:7B:03:22:8D:9E:AF:32:0B:84:89:80:80:0C:1E:C2
X509v3 Authority Key Identifier:
- keyid:41:C9:49:37:B1:FA:61:E3:BA:D7:19:3D:D9:DA:8C:B9:82:C9:B4:6A
+ keyid:E8:7E:58:AC:13:7B:03:22:8D:9E:AF:32:0B:84:89:80:80:0C:1E:C2
+ DirName:/C=JP/ST=Shimane/L=Matz-e city/O=Ruby Core Team/CN=Ruby Test CA/emailAddress=security@ruby-lang.org
+ serial:B9:90:A2:BF:62:69:17:9C
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha1WithRSAEncryption
- 86:00:33:b9:dd:ff:5f:83:59:5f:c3:29:3c:d7:11:db:10:b3:
- d7:d1:70:fb:0a:c6:74:85:c6:ea:e1:15:c4:92:f8:0e:11:cc:
- ff:a6:3c:31:c2:2c:66:d8:fe:63:93:9f:b0:97:e6:f5:bc:5c:
- 80:68:96:5d:eb:77:b9:23:dd:68:a7:49:03:ff:22:48:55:f1:
- 39:7c:20:21:ff:64:52:e1:f6:cf:3c:b3:4d:2c:5c:03:62:ea:
- c5:49:99:07:fa:8d:ff:7b:c2:75:0c:ca:24:b5:0b:f5:b7:57:
- 3a:10:f0:8a:bb:9a:e8:92:4d:d5:6f:c2:a2:29:36:61:78:a4:
- dc:7b
+ 8f:77:06:4e:31:72:12:ee:68:09:70:27:d4:31:85:ef:10:95:
+ f9:0f:2b:66:63:08:37:88:6e:b7:9b:40:3e:18:77:33:86:e8:
+ 61:6a:b7:3c:cb:c7:a6:d6:d5:92:6a:1f:56:d0:9f:5c:32:56:
+ d3:37:52:fe:0e:20:c2:7a:0d:fe:2d:3c:81:da:b8:7f:4d:6a:
+ 08:01:d9:be:7a:a2:15:be:a6:ce:49:64:90:8c:9a:ca:6e:2e:
+ 84:48:1d:94:19:56:94:46:aa:25:9b:68:c2:80:60:bf:cb:2e:
+ 35:03:ea:0a:65:5a:33:38:c6:cc:81:46:c0:bc:36:86:96:39:
+ 10:7d
-----BEGIN CERTIFICATE-----
-MIIC6DCCAlGgAwIBAgIJAJ/c95SYBUNMMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYD
-VQQGEwJKUDEQMA4GA1UECAwHU2hpbWFuZTEUMBIGA1UEBwwLTWF0ei1lIGNpdHkx
-FzAVBgNVBAoMDlJ1YnkgQ29yZSBUZWFtMRUwEwYDVQQDDAxSdWJ5IFRlc3QgQ0Ex
-JTAjBgkqhkiG9w0BCQEWFnNlY3VyaXR5QHJ1YnktbGFuZy5vcmcwHhcNMTAxMjIz
-MTAyMTMzWhcNMTQwMTAxMTAyMTMzWjCBjDELMAkGA1UEBhMCSlAxEDAOBgNVBAgM
-B1NoaW1hbmUxFDASBgNVBAcMC01hdHotZSBjaXR5MRcwFQYDVQQKDA5SdWJ5IENv
-cmUgVGVhbTEVMBMGA1UEAwwMUnVieSBUZXN0IENBMSUwIwYJKoZIhvcNAQkBFhZz
+MIIDjTCCAvagAwIBAgIJALmQor9iaRecMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYD
+VQQGEwJKUDEQMA4GA1UECBMHU2hpbWFuZTEUMBIGA1UEBxMLTWF0ei1lIGNpdHkx
+FzAVBgNVBAoTDlJ1YnkgQ29yZSBUZWFtMRUwEwYDVQQDEwxSdWJ5IFRlc3QgQ0Ex
+JTAjBgkqhkiG9w0BCQEWFnNlY3VyaXR5QHJ1YnktbGFuZy5vcmcwHhcNMTQwMTAz
+MDEzNDE3WhcNMTkwMTAyMDEzNDE3WjCBjDELMAkGA1UEBhMCSlAxEDAOBgNVBAgT
+B1NoaW1hbmUxFDASBgNVBAcTC01hdHotZSBjaXR5MRcwFQYDVQQKEw5SdWJ5IENv
+cmUgVGVhbTEVMBMGA1UEAxMMUnVieSBUZXN0IENBMSUwIwYJKoZIhvcNAQkBFhZz
ZWN1cml0eUBydWJ5LWxhbmcub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDOviyfR7rbnJxb8Dg783QgN3Yjn4QcgZC0PgAgNJh+gWlQocNllur6ANqMzFM/
-ujzQUHpatGus0y4Yyipps2pvOMIyqAa2CjCp7gM46QWlGSNUqDy5CK0rciPfkyLE
-Rqjq8abpMEo/gznpYo6Lo15niR18dd4Fqlixt3l8EIBthwIDAQABo1AwTjAdBgNV
-HQ4EFgQUQclJN7H6YeO61xk92dqMuYLJtGowHwYDVR0jBBgwFoAUQclJN7H6YeO6
-1xk92dqMuYLJtGowDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCGADO5
-3f9fg1lfwyk81xHbELPX0XD7CsZ0hcbq4RXEkvgOEcz/pjwxwixm2P5jk5+wl+b1
-vFyAaJZd63e5I91op0kD/yJIVfE5fCAh/2RS4fbPPLNNLFwDYurFSZkH+o3/e8J1
-DMoktQv1t1c6EPCKu5rokk3Vb8KiKTZheKTcew==
+gQDbddBF3rHfv3GgDrCl5rz0HJ3lJWdkxXvL8a/Gvpqq6n4PzAWv70BpBrLJE51+
+66IG4up9B8fHmcf71bjrY3diKxgSw1NY0PXHQAwB0SaCNBYJ49xl9Ny7XaVBYOep
+dLrXTLajnMWMia/L6J8F/ur+ZCS/5+3j9tD81uv8BoIQ+wIDAQABo4H0MIHxMB0G
+A1UdDgQWBBToflisE3sDIo2erzILhImAgAwewjCBwQYDVR0jBIG5MIG2gBToflis
+E3sDIo2erzILhImAgAwewqGBkqSBjzCBjDELMAkGA1UEBhMCSlAxEDAOBgNVBAgT
+B1NoaW1hbmUxFDASBgNVBAcTC01hdHotZSBjaXR5MRcwFQYDVQQKEw5SdWJ5IENv
+cmUgVGVhbTEVMBMGA1UEAxMMUnVieSBUZXN0IENBMSUwIwYJKoZIhvcNAQkBFhZz
+ZWN1cml0eUBydWJ5LWxhbmcub3JnggkAuZCiv2JpF5wwDAYDVR0TBAUwAwEB/zAN
+BgkqhkiG9w0BAQUFAAOBgQCPdwZOMXIS7mgJcCfUMYXvEJX5DytmYwg3iG63m0A+
+GHczhuhharc8y8em1tWSah9W0J9cMlbTN1L+DiDCeg3+LTyB2rh/TWoIAdm+eqIV
+vqbOSWSQjJrKbi6ESB2UGVaURqolm2jCgGC/yy41A+oKZVozOMbMgUbAvDaGljkQ
+fQ==
-----END CERTIFICATE-----
diff --git a/test/net/imap/server.crt b/test/net/imap/server.crt
index d848b26ab0..fa4f99493a 100644
--- a/test/net/imap/server.crt
+++ b/test/net/imap/server.crt
@@ -1,17 +1,17 @@
Certificate:
Data:
- Version: 3 (0x2)
+ Version: 1 (0x0)
Serial Number: 0 (0x0)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=JP, ST=Shimane, L=Matz-e city, O=Ruby Core Team, CN=Ruby Test CA/emailAddress=security@ruby-lang.org
Validity
- Not Before: Dec 23 10:23:52 2010 GMT
- Not After : Jan 1 10:23:52 2014 GMT
+ Not Before: Jan 3 01:34:17 2014 GMT
+ Not After : Jan 2 01:34:17 2019 GMT
Subject: C=JP, ST=Shimane, O=Ruby Core Team, OU=Ruby Test, CN=localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
- Modulus:
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
00:db:75:d0:45:de:b1:df:bf:71:a0:0e:b0:a5:e6:
bc:f4:1c:9d:e5:25:67:64:c5:7b:cb:f1:af:c6:be:
9a:aa:ea:7e:0f:cc:05:af:ef:40:69:06:b2:c9:13:
@@ -22,40 +22,27 @@ Certificate:
af:cb:e8:9f:05:fe:ea:fe:64:24:bf:e7:ed:e3:f6:
d0:fc:d6:eb:fc:06:82:10:fb
Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints:
- CA:FALSE
- Netscape Comment:
- OpenSSL Generated Certificate
- X509v3 Subject Key Identifier:
- E8:7E:58:AC:13:7B:03:22:8D:9E:AF:32:0B:84:89:80:80:0C:1E:C2
- X509v3 Authority Key Identifier:
- keyid:41:C9:49:37:B1:FA:61:E3:BA:D7:19:3D:D9:DA:8C:B9:82:C9:B4:6A
-
Signature Algorithm: sha1WithRSAEncryption
- ae:ee:cd:fe:c9:af:48:0b:50:37:ac:6a:f6:68:90:9b:67:df:
- 6f:2d:17:c9:3c:a5:da:ad:39:dc:2a:5b:07:88:26:38:19:30:
- d6:95:cf:10:69:c7:92:14:83:be:f1:b5:8e:6f:d9:91:51:c5:
- 63:ae:1c:89:ac:27:bf:4f:2a:8f:4e:0c:57:42:0a:c9:8e:0c:
- f4:f3:02:f7:ea:44:b6:e4:47:05:af:4e:74:e4:87:87:d9:c8:
- 76:ed:ab:32:7c:f0:31:34:10:14:bc:a6:37:cd:d7:dc:33:da:
- 82:d3:d4:9b:e9:d5:cd:38:cc:fa:81:5f:4e:fd:5f:53:05:5d:
- 76:f9
+ 85:f5:d3:05:8b:8c:f4:43:1c:88:f2:8f:b2:f2:93:77:b7:3d:
+ 95:c6:a0:34:bc:33:6a:d8:85:5f:3e:86:08:10:c5:5c:c1:76:
+ a3:53:3c:dc:38:98:23:97:e7:da:21:ac:e8:4d:3c:96:70:29:
+ ff:ff:1e:4a:9a:17:2b:db:04:62:b9:ef:ab:ea:a7:a5:e8:7c:
+ b1:d5:ed:30:a8:6c:78:de:51:7e:e3:8a:c2:a4:64:a8:63:a2:
+ bc:fd:43:9c:f3:55:7d:54:c9:6a:d8:53:1c:4b:6b:03:aa:b6:
+ 19:e6:a4:4f:47:00:96:c5:42:59:85:4e:c3:4e:cd:41:82:53:
+ 10:f8
-----BEGIN CERTIFICATE-----
-MIIC3jCCAkegAwIBAgIBADANBgkqhkiG9w0BAQUFADCBjDELMAkGA1UEBhMCSlAx
-EDAOBgNVBAgMB1NoaW1hbmUxFDASBgNVBAcMC01hdHotZSBjaXR5MRcwFQYDVQQK
-DA5SdWJ5IENvcmUgVGVhbTEVMBMGA1UEAwwMUnVieSBUZXN0IENBMSUwIwYJKoZI
-hvcNAQkBFhZzZWN1cml0eUBydWJ5LWxhbmcub3JnMB4XDTEwMTIyMzEwMjM1MloX
-DTE0MDEwMTEwMjM1MlowYDELMAkGA1UEBhMCSlAxEDAOBgNVBAgMB1NoaW1hbmUx
-FzAVBgNVBAoMDlJ1YnkgQ29yZSBUZWFtMRIwEAYDVQQLDAlSdWJ5IFRlc3QxEjAQ
-BgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA23XQ
-Rd6x379xoA6wpea89Byd5SVnZMV7y/Gvxr6aqup+D8wFr+9AaQayyROdfuuiBuLq
-fQfHx5nH+9W462N3YisYEsNTWND1x0AMAdEmgjQWCePcZfTcu12lQWDnqXS610y2
-o5zFjImvy+ifBf7q/mQkv+ft4/bQ/Nbr/AaCEPsCAwEAAaN7MHkwCQYDVR0TBAIw
-ADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUw
-HQYDVR0OBBYEFOh+WKwTewMijZ6vMguEiYCADB7CMB8GA1UdIwQYMBaAFEHJSTex
-+mHjutcZPdnajLmCybRqMA0GCSqGSIb3DQEBBQUAA4GBAK7uzf7Jr0gLUDesavZo
-kJtn328tF8k8pdqtOdwqWweIJjgZMNaVzxBpx5IUg77xtY5v2ZFRxWOuHImsJ79P
-Ko9ODFdCCsmODPTzAvfqRLbkRwWvTnTkh4fZyHbtqzJ88DE0EBS8pjfN19wz2oLT
-1Jvp1c04zPqBX079X1MFXXb5
+MIICXDCCAcUCAQAwDQYJKoZIhvcNAQEFBQAwgYwxCzAJBgNVBAYTAkpQMRAwDgYD
+VQQIEwdTaGltYW5lMRQwEgYDVQQHEwtNYXR6LWUgY2l0eTEXMBUGA1UEChMOUnVi
+eSBDb3JlIFRlYW0xFTATBgNVBAMTDFJ1YnkgVGVzdCBDQTElMCMGCSqGSIb3DQEJ
+ARYWc2VjdXJpdHlAcnVieS1sYW5nLm9yZzAeFw0xNDAxMDMwMTM0MTdaFw0xOTAx
+MDIwMTM0MTdaMGAxCzAJBgNVBAYTAkpQMRAwDgYDVQQIEwdTaGltYW5lMRcwFQYD
+VQQKEw5SdWJ5IENvcmUgVGVhbTESMBAGA1UECxMJUnVieSBUZXN0MRIwEAYDVQQD
+Ewlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANt10EXesd+/
+caAOsKXmvPQcneUlZ2TFe8vxr8a+mqrqfg/MBa/vQGkGsskTnX7rogbi6n0Hx8eZ
+x/vVuOtjd2IrGBLDU1jQ9cdADAHRJoI0Fgnj3GX03LtdpUFg56l0utdMtqOcxYyJ
+r8vonwX+6v5kJL/n7eP20PzW6/wGghD7AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEA
+hfXTBYuM9EMciPKPsvKTd7c9lcagNLwzatiFXz6GCBDFXMF2o1M83DiYI5fn2iGs
+6E08lnAp//8eSpoXK9sEYrnvq+qnpeh8sdXtMKhseN5RfuOKwqRkqGOivP1DnPNV
+fVTJathTHEtrA6q2GeakT0cAlsVCWYVOw07NQYJTEPg=
-----END CERTIFICATE-----
diff --git a/test/net/imap/test_imap_response_parser.rb b/test/net/imap/test_imap_response_parser.rb
index 6a5a117408..1547a05b2e 100644
--- a/test/net/imap/test_imap_response_parser.rb
+++ b/test/net/imap/test_imap_response_parser.rb
@@ -116,4 +116,29 @@ EOF
* 1 FETCH (UID 92285 )
EOF
end
+
+ # [Bug #8281]
+ def test_acl
+ parser = Net::IMAP::ResponseParser.new
+ response = parser.parse(<<EOF.gsub(/\n/, "\r\n").taint)
+* ACL "INBOX/share" "imshare2copy1366146467@xxxxxxxxxxxxxxxxxx.com" lrswickxteda
+EOF
+ assert_equal("ACL", response.name)
+ assert_equal(1, response.data.length)
+ assert_equal("INBOX/share", response.data[0].mailbox)
+ assert_equal("imshare2copy1366146467@xxxxxxxxxxxxxxxxxx.com",
+ response.data[0].user)
+ assert_equal("lrswickxteda", response.data[0].rights)
+ end
+
+ # [Bug #8415]
+ def test_capability
+ parser = Net::IMAP::ResponseParser.new
+ response = parser.parse("* CAPABILITY st11p00mm-iscream009 1Q49 XAPPLEPUSHSERVICE IMAP4 IMAP4rev1 SASL-IR AUTH=ATOKEN AUTH=PLAIN\r\n")
+ assert_equal("CAPABILITY", response.name)
+ assert_equal("AUTH=PLAIN", response.data.last)
+ response = parser.parse("* CAPABILITY st11p00mm-iscream009 1Q49 XAPPLEPUSHSERVICE IMAP4 IMAP4rev1 SASL-IR AUTH=ATOKEN AUTH=PLAIN \r\n")
+ assert_equal("CAPABILITY", response.name)
+ assert_equal("AUTH=PLAIN", response.data.last)
+ end
end
diff --git a/test/net/smtp/test_smtp.rb b/test/net/smtp/test_smtp.rb
index 8af6a37d53..ba2943db56 100644
--- a/test/net/smtp/test_smtp.rb
+++ b/test/net/smtp/test_smtp.rb
@@ -3,6 +3,19 @@ require 'minitest/autorun'
module Net
class TestSMTP < MiniTest::Unit::TestCase
+ def test_critical
+ smtp = Net::SMTP.new 'localhost', 25
+
+ assert_raises RuntimeError do
+ smtp.send :critical do
+ raise 'fail on purpose'
+ end
+ end
+
+ assert_kind_of Net::SMTP::Response, smtp.send(:critical),
+ '[Bug #9125]'
+ end
+
def test_esmtp
smtp = Net::SMTP.new 'localhost', 25
assert smtp.esmtp
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index 811fe387fa..3e6d3c9a42 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -263,6 +263,14 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
end
end
+ def test_decode_utctime
+ expected = Time.at 1374535380
+ assert_equal expected, OpenSSL::ASN1.decode("\x17\v1307222323Z").value
+
+ expected += 17
+ assert_equal expected, OpenSSL::ASN1.decode("\x17\r130722232317Z").value
+ end
+
def test_create_inf_length_primitive
expected = %w{ 24 80 04 01 61 00 00 }
raw = [expected.join('')].pack('H*')
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index e63f617140..0856c2785e 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -7,28 +7,29 @@ class OpenSSL::TestEC < Test::Unit::TestCase
@data1 = 'foo'
@data2 = 'bar' * 1000 # data too long for DSA sig
- @group1 = OpenSSL::PKey::EC::Group.new('secp112r1')
- @group2 = OpenSSL::PKey::EC::Group.new('sect163k1')
- @group3 = OpenSSL::PKey::EC::Group.new('prime256v1')
+ @groups = []
+ @keys = []
- @key1 = OpenSSL::PKey::EC.new
- @key1.group = @group1
- @key1.generate_key
+ OpenSSL::PKey::EC.builtin_curves.each do |curve, comment|
+ next if curve.start_with?("Oakley") # Oakley curves are not suitable for ECDSA
+ group = OpenSSL::PKey::EC::Group.new(curve)
- @key2 = OpenSSL::PKey::EC.new(@group2.curve_name)
- @key2.generate_key
+ key = OpenSSL::PKey::EC.new(group)
+ key.generate_key
- @key3 = OpenSSL::PKey::EC.new(@group3)
- @key3.generate_key
-
- @groups = [@group1, @group2, @group3]
- @keys = [@key1, @key2, @key3]
+ @groups << group
+ @keys << key
+ end
end
def compare_keys(k1, k2)
assert_equal(k1.to_pem, k2.to_pem)
end
+ def test_builtin_curves
+ assert(!OpenSSL::PKey::EC.builtin_curves.empty?)
+ end
+
def test_curve_names
@groups.each_with_index do |group, idx|
key = @keys[idx]
@@ -44,11 +45,12 @@ class OpenSSL::TestEC < Test::Unit::TestCase
end
end
- def test_encoding
+ def test_group_encoding
for group in @groups
for meth in [:to_der, :to_pem]
txt = group.send(meth)
gr = OpenSSL::PKey::EC::Group.new(txt)
+
assert_equal(txt, gr.send(meth))
assert_equal(group.generator.to_bn, gr.generator.to_bn)
@@ -58,7 +60,9 @@ class OpenSSL::TestEC < Test::Unit::TestCase
assert_equal(group.degree, gr.degree)
end
end
+ end
+ def test_key_encoding
for key in @keys
group = key.group
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index 5d40a5576b..2b92cf9701 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -351,6 +351,35 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_verify_certificate_identity
+ [true, false].each do |criticality|
+ cert = create_null_byte_SAN_certificate(criticality)
+ assert_equal(false, OpenSSL::SSL.verify_certificate_identity(cert, 'www.example.com'))
+ assert_equal(true, OpenSSL::SSL.verify_certificate_identity(cert, "www.example.com\0.evil.com"))
+ assert_equal(false, OpenSSL::SSL.verify_certificate_identity(cert, '192.168.7.255'))
+ assert_equal(true, OpenSSL::SSL.verify_certificate_identity(cert, '192.168.7.1'))
+ assert_equal(false, OpenSSL::SSL.verify_certificate_identity(cert, '13::17'))
+ assert_equal(true, OpenSSL::SSL.verify_certificate_identity(cert, '13:0:0:0:0:0:0:17'))
+ end
+ end
+
+ # Create NULL byte SAN certificate
+ def create_null_byte_SAN_certificate(critical = false)
+ ef = OpenSSL::X509::ExtensionFactory.new
+ cert = OpenSSL::X509::Certificate.new
+ cert.subject = OpenSSL::X509::Name.parse "/DC=some/DC=site/CN=Some Site"
+ ext = ef.create_ext('subjectAltName', 'DNS:placeholder,IP:192.168.7.1,IP:13::17', critical)
+ ext_asn1 = OpenSSL::ASN1.decode(ext.to_der)
+ san_list_der = ext_asn1.value.reduce(nil) { |memo,val| val.tag == 4 ? val.value : memo }
+ san_list_asn1 = OpenSSL::ASN1.decode(san_list_der)
+ san_list_asn1.value[0].value = "www.example.com\0.evil.com"
+ pos = critical ? 2 : 1
+ ext_asn1.value[pos].value = san_list_asn1.to_der
+ real_ext = OpenSSL::X509::Extension.new ext_asn1
+ cert.add_extension(real_ext)
+ cert
+ end
+
def test_tlsext_hostname
return unless OpenSSL::SSL::SSLSocket.instance_methods.include?(:hostname)
@@ -438,6 +467,33 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_invalid_shutdown_by_gc
+ assert_nothing_raised {
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ 10.times {
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ GC.start
+ ssl.connect
+ sock.close
+ }
+ }
+ }
+ end
+
+ def test_close_after_socket_close
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.sync_close = true
+ ssl.connect
+ sock.close
+ assert_nothing_raised do
+ ssl.close
+ end
+ }
+ end
+
end
end
diff --git a/test/optparse/test_acceptable.rb b/test/optparse/test_acceptable.rb
new file mode 100644
index 0000000000..6ec619ef8c
--- /dev/null
+++ b/test/optparse/test_acceptable.rb
@@ -0,0 +1,195 @@
+require_relative 'test_optparse'
+
+class TestOptionParser::Acceptable < TestOptionParser
+
+ def setup
+ super
+ @opt.def_option("--integer VAL", Integer) { |v| @integer = v }
+ @opt.def_option("--float VAL", Float) { |v| @float = v }
+ @opt.def_option("--numeric VAL", Numeric) { |v| @numeric = v }
+
+ @opt.def_option("--decimal-integer VAL",
+ OptionParser::DecimalInteger) { |i| @decimal_integer = i }
+ @opt.def_option("--octal-integer VAL",
+ OptionParser::OctalInteger) { |i| @octal_integer = i }
+ @opt.def_option("--decimal-numeric VAL",
+ OptionParser::DecimalNumeric) { |i| @decimal_numeric = i }
+ end
+
+ def test_integer
+ assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0")})
+ assert_equal(0, @integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0b10")})
+ assert_equal(2, @integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--integer 077")})
+ assert_equal(63, @integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--integer 10")})
+ assert_equal(10, @integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--integer 0x3")})
+ assert_equal(3, @integer)
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--integer 0b")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--integer 09")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--integer 0x")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--integer 1234xyz")
+ end
+ end
+
+ def test_float
+ assert_equal(%w"", no_error {@opt.parse!(%w"--float 0")})
+ assert_in_epsilon(0.0, @float)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--float 0.0")})
+ assert_in_epsilon(0.0, @float)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--float 1.2")})
+ assert_in_epsilon(1.2, @float)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--float 1E2")})
+ assert_in_epsilon(100, @float)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--float 1E-2")})
+ assert_in_epsilon(0.01, @float)
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--float 0e")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--float 1.234xyz")
+ end
+ end
+
+ def test_numeric
+ assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 0")})
+ assert_equal(0, @numeric)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 0/1")})
+ assert_equal(0, @numeric)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 1/2")})
+ assert_equal(Rational(1, 2), @numeric)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--numeric 1.2/2.3")})
+ assert_equal(Rational(12, 23), @numeric)
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--numeric 1/")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--numeric 12/34xyz")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--numeric 12x/34yz")
+ end
+ end
+
+ def test_decimal_integer
+ assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 0")})
+ assert_equal(0, @decimal_integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-integer 10")})
+ assert_equal(10, @decimal_integer)
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--decimal-integer 0b1")
+ end
+
+ e = assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--decimal-integer 09")
+ end
+
+ assert_equal("invalid argument: --decimal-integer 09", e.message)
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--decimal-integer x")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--decimal-integer 1234xyz")
+ end
+ end
+
+ def test_octal_integer
+ assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 0")})
+ assert_equal(0, @octal_integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 6")})
+ assert_equal(6, @octal_integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 07")})
+ assert_equal(7, @octal_integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 10")})
+ assert_equal(8, @octal_integer)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--octal-integer 011")})
+ assert_equal(9, @octal_integer)
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--octal-integer 09")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--octal-integer 0b1")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--octal-integer x")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--octal-integer 01234xyz")
+ end
+ end
+
+ def test_decimal_numeric
+ assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 0")})
+ assert_equal(0, @decimal_numeric)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 01")})
+ assert_equal(1, @decimal_numeric)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 1.2")})
+ assert_in_delta(1.2, @decimal_numeric)
+
+ assert_equal(%w"", no_error {@opt.parse!(%w"--decimal-numeric 1E2")})
+ assert_in_delta(100.0, @decimal_numeric)
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--decimal-numeric 0b1")
+ end
+
+ e = assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--decimal-numeric 09")
+ end
+
+ assert_equal("invalid argument: --decimal-numeric 09", e.message)
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--decimal-integer 1234xyz")
+ end
+
+ assert_raises(OptionParser::InvalidArgument) do
+ @opt.parse!(%w"--decimal-integer 12.34xyz")
+ end
+ end
+
+end
+
diff --git a/test/resolv/test_addr.rb b/test/resolv/test_addr.rb
index 84bc8c2d3b..b4718430cc 100644
--- a/test/resolv/test_addr.rb
+++ b/test/resolv/test_addr.rb
@@ -1,6 +1,7 @@
require 'test/unit'
require 'resolv'
require 'socket'
+require 'tempfile'
class TestResolvAddr < Test::Unit::TestCase
def test_invalid_ipv4_address
@@ -13,4 +14,16 @@ class TestResolvAddr < Test::Unit::TestCase
end
}
end
+
+ def test_invalid_byte_comment
+ bug9273 = '[ruby-core:59239] [Bug #9273]'
+ Tempfile.open('resolv_test_addr_') do |tmpfile|
+ tmpfile.print("\xff\x00\x40")
+ tmpfile.close
+ hosts = Resolv::Hosts.new(tmpfile.path)
+ assert_nothing_raised(ArgumentError, bug9273) do
+ hosts.each_address("") {break}
+ end
+ end
+ end
end
diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb
index 9a9c33ea84..0b2a8aacd6 100644
--- a/test/resolv/test_dns.rb
+++ b/test/resolv/test_dns.rb
@@ -1,6 +1,7 @@
require 'test/unit'
require 'resolv'
require 'socket'
+require 'tempfile'
class TestResolvDNS < Test::Unit::TestCase
def setup
@@ -118,4 +119,14 @@ class TestResolvDNS < Test::Unit::TestCase
}
end
+ def test_invalid_byte_comment
+ bug9273 = '[ruby-core:59239] [Bug #9273]'
+ Tempfile.open('resolv_test_dns_') do |tmpfile|
+ tmpfile.print("\xff\x00\x40")
+ tmpfile.close
+ assert_nothing_raised(ArgumentError, bug9273) do
+ Resolv::DNS::Config.parse_resolv_conf(tmpfile.path)
+ end
+ end
+ end
end
diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb
index af41d3e6a4..1e3e6a3625 100644
--- a/test/ripper/test_parser_events.rb
+++ b/test/ripper/test_parser_events.rb
@@ -24,6 +24,10 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
dp.parse.to_s
end
+ def compile_error(str)
+ parse(str, :compile_error) {|e, msg| return msg}
+ end
+
def test_program
thru_program = false
assert_equal '[void()]', parse('', :on_program) {thru_program = true}
@@ -1135,8 +1139,20 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def test_unterminated_regexp
- compile_error = false
- parse('/', :compile_error) {|e, msg| compile_error = msg}
- assert_equal("unterminated regexp meets end of file", compile_error)
+ assert_equal("unterminated regexp meets end of file", compile_error('/'))
+ end
+
+ def test_invalid_instance_variable_name
+ assert_equal("`@1' is not allowed as an instance variable name", compile_error('@1'))
+ assert_equal("`@%' is not allowed as an instance variable name", compile_error('@%'))
+ end
+
+ def test_invalid_class_variable_name
+ assert_equal("`@@1' is not allowed as a class variable name", compile_error('@@1'))
+ assert_equal("`@@%' is not allowed as a class variable name", compile_error('@@%'))
+ end
+
+ def test_invalid_global_variable_name
+ assert_equal("`$%' is not allowed as a global variable name", compile_error('$%'))
end
end if ripper_test
diff --git a/test/ripper/test_scanner_events.rb b/test/ripper/test_scanner_events.rb
index c92ec494ed..0f61ac7880 100644
--- a/test/ripper/test_scanner_events.rb
+++ b/test/ripper/test_scanner_events.rb
@@ -90,28 +90,28 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
end
def test_location
- validate_location ""
- validate_location " "
- validate_location "@"
- validate_location "\n"
- validate_location "\r\n"
- validate_location "\n\n\n\n\n\r\n\n\n"
- validate_location "\n;\n;\n;\n;\n"
- validate_location "nil"
- validate_location "@ivar"
- validate_location "1;2;3"
- validate_location "1\n2\n3"
- validate_location "1\n2\n3\n"
- validate_location "def m(a) nil end"
- validate_location "if true then false else nil end"
- validate_location "BEGIN{print nil}"
- validate_location "%w(a b\nc\r\nd \ne )"
- validate_location %Q["a\nb\r\nc"]
- validate_location "print(<<EOS)\nheredoc\nEOS\n"
- validate_location "print(<<-\"EOS\")\nheredoc\n EOS\n"
- end
-
- def validate_location(src)
+ assert_location ""
+ assert_location " "
+ assert_location ":"
+ assert_location "\n"
+ assert_location "\r\n"
+ assert_location "\n\n\n\n\n\r\n\n\n"
+ assert_location "\n;\n;\n;\n;\n"
+ assert_location "nil"
+ assert_location "@ivar"
+ assert_location "1;2;3"
+ assert_location "1\n2\n3"
+ assert_location "1\n2\n3\n"
+ assert_location "def m(a) nil end"
+ assert_location "if true then false else nil end"
+ assert_location "BEGIN{print nil}"
+ assert_location "%w(a b\nc\r\nd \ne )"
+ assert_location %Q["a\nb\r\nc"]
+ assert_location "print(<<""EOS)\nheredoc\nEOS\n"
+ assert_location "print(<<-\"EOS\")\nheredoc\n EOS\n"
+ end
+
+ def assert_location(src)
buf = ''
Ripper.lex(src).each do |pos, type, tok|
line, col = *pos
@@ -823,8 +823,8 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
def test_CHAR
assert_equal [],
scan('CHAR', "")
- assert_equal ["@"],
- scan('CHAR', "@")
+ assert_equal ["?a"],
+ scan('CHAR', "?a")
assert_equal [],
scan('CHAR', "@ivar")
end
diff --git a/test/ruby/envutil.rb b/test/ruby/envutil.rb
index 73f0101ac1..6998842259 100644
--- a/test/ruby/envutil.rb
+++ b/test/ruby/envutil.rb
@@ -184,6 +184,31 @@ module Test
assert(msg === stderr, "warning message #{stderr.inspect} is expected to match #{msg.inspect}")
end
+ def assert_no_memory_leak(args, prepare, code, message=nil, opt = {})
+ limit = opt.delete(:limit) || 1.5
+ token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m"
+ token_dump = token.dump
+ token_re = Regexp.quote(token)
+ envs = args.shift if Array === args and Hash === args.first
+ args = [
+ "--disable=gems",
+ "-r", File.expand_path("../memory_status", __FILE__),
+ *args,
+ "-v", "-",
+ ]
+ args.unshift(envs) if envs
+ cmd = [
+ 'END {STDERR.puts '"#{token_dump}"'"FINAL=#{Memory::Status.new.size}"}',
+ prepare,
+ 'STDERR.puts('"#{token_dump}"'"START=#{$initial_size = Memory::Status.new.size}")',
+ code,
+ ].join("\n")
+ _, err, status = EnvUtil.invoke_ruby(args, cmd, true, true, opt)
+ before = err.sub!(/^#{token_re}START=(\d+)\n/, '') && $1.to_i
+ after = err.sub!(/^#{token_re}FINAL=(\d+)\n/, '') && $1.to_i
+ assert_equal([true, ""], [status.success?, err], message)
+ assert_operator(after.fdiv(before), :<, limit, message)
+ end
def assert_is_minus_zero(f)
assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0")
diff --git a/test/ruby/memory_status.rb b/test/ruby/memory_status.rb
index f504c0a736..cd4a62c1c0 100644
--- a/test/ruby/memory_status.rb
+++ b/test/ruby/memory_status.rb
@@ -7,7 +7,7 @@ module Memory
PROC_FILE = procfile
VM_PAT = /^Vm(\w+):\s+(\d+)/
def self.read_status
- IO.foreach(PROC_FILE) do |l|
+ IO.foreach(PROC_FILE, encoding: Encoding::ASCII_8BIT) do |l|
yield($1.downcase.intern, $2.to_i * 1024) if VM_PAT =~ l
end
end
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 28d3e4156b..4350e0578f 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -552,6 +552,29 @@ class TestArray < Test::Unit::TestCase
assert_equal(3, a.count {|x| x % 2 == 1 })
assert_equal(2, a.count(1) {|x| x % 2 == 1 })
assert_raise(ArgumentError) { a.count(0, 1) }
+
+ bug8654 = '[ruby-core:56072]'
+ assert_in_out_err [], <<-EOS, ["0"], [], bug8654
+ a1 = []
+ a2 = Array.new(100) { |i| i }
+ a2.count do |i|
+ p i
+ a2.replace(a1) if i == 0
+ end
+ EOS
+
+ assert_in_out_err [], <<-EOS, ["[]", "0"], [], bug8654
+ ARY = Array.new(100) { |i| i }
+ class Fixnum
+ alias old_equal ==
+ def == other
+ ARY.replace([]) if self.equal?(0)
+ p ARY
+ self.equal?(other)
+ end
+ end
+ p ARY.count(42)
+ EOS
end
def test_delete
@@ -1624,8 +1647,8 @@ class TestArray < Test::Unit::TestCase
[2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]],
a.repeated_combination(4).to_a.sort)
assert_equal(@cls[], a.repeated_combination(-1).to_a)
- assert_equal("abcde".each_char.to_a.repeated_combination(5).map{|a|a.sort}.sort,
- "edcba".each_char.to_a.repeated_combination(5).map{|a|a.sort}.sort)
+ assert_equal("abcde".each_char.to_a.repeated_combination(5).map{|e|e.sort}.sort,
+ "edcba".each_char.to_a.repeated_combination(5).map{|e|e.sort}.sort)
assert_equal(@cls[].repeated_combination(0).to_a, @cls[[]])
assert_equal(@cls[].repeated_combination(1).to_a, @cls[])
diff --git a/test/ruby/test_beginendblock.rb b/test/ruby/test_beginendblock.rb
index b590835a2d..121d116c35 100644
--- a/test/ruby/test_beginendblock.rb
+++ b/test/ruby/test_beginendblock.rb
@@ -158,4 +158,15 @@ EOW
assert_equal(["", "", 42], [out, err, status.exitstatus], "#{bug5218}: #{ex}")
end
end
+
+ def test_callcc_at_exit
+ bug9110 = '[ruby-core:58329][Bug #9110]'
+ script = <<EOS
+require "continuation"
+c = nil
+at_exit { c.call }
+at_exit { callcc {|_c| c = _c } }
+EOS
+ assert_normal_exit(script, bug9110)
+ end
end
diff --git a/test/ruby/test_comparable.rb b/test/ruby/test_comparable.rb
index 00ce6b485a..3526c73add 100644
--- a/test/ruby/test_comparable.rb
+++ b/test/ruby/test_comparable.rb
@@ -69,4 +69,11 @@ class TestComparable < Test::Unit::TestCase
assert_raise(ArgumentError) { 1.0 < nil }
assert_raise(ArgumentError) { 1.0 < Object.new }
end
+
+ def test_no_cmp
+ bug9003 = '[ruby-core:57736] [Bug #9003]'
+ assert_nothing_raised(SystemStackError, bug9003) {
+ @o <=> @o.dup
+ }
+ end
end
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
index 10ba2f184e..feaa2de698 100644
--- a/test/ruby/test_enumerator.rb
+++ b/test/ruby/test_enumerator.rb
@@ -1,4 +1,5 @@
require 'test/unit'
+require_relative "envutil"
class TestEnumerator < Test::Unit::TestCase
def setup
@@ -97,6 +98,36 @@ class TestEnumerator < Test::Unit::TestCase
assert_equal([[1,5],[2,6],[3,7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a)
end
+ def test_with_index_large_offset
+ bug8010 = '[ruby-dev:47131] [Bug #8010]'
+ s = 1 << (8*1.size-2)
+ assert_equal([[1,s],[2,s+1],[3,s+2]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a, bug8010)
+ s <<= 1
+ assert_equal([[1,s],[2,s+1],[3,s+2]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a, bug8010)
+ end
+
+ def test_with_index_nonnum_offset
+ bug8010 = '[ruby-dev:47131] [Bug #8010]'
+ s = Object.new
+ def s.to_int; 1 end
+ assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a, bug8010)
+ end
+
+ def test_with_index_string_offset
+ bug8010 = '[ruby-dev:47131] [Bug #8010]'
+ assert_raise(TypeError, bug8010){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a }
+ end
+
+ def test_with_index_dangling_memo
+ bug9178 = '[ruby-core:58692] [Bug #9178]'
+ assert_in_out_err([], <<-"end;", ["Enumerator", "[false, [1]]"], [], bug9178)
+ bug = "#{bug9178}"
+ e = [1].to_enum(:chunk).with_index {|c,i| i == 5}
+ puts e.class
+ p e.to_a[0]
+ end;
+ end
+
def test_with_object
obj = [0, 1]
ret = (1..10).each.with_object(obj) {|i, memo|
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index d2cee75433..301aeecf0f 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -519,4 +519,16 @@ class TestFloat < Test::Unit::TestCase
sleep(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1)
end
end
+
+ def test_long_string
+ assert_normal_exit(<<-'end;')
+ assert_in_epsilon(10.0, ("1."+"1"*300000).to_f*9)
+ end;
+ end
+
+ def test_long_string
+ assert_normal_exit(<<-'end;')
+ assert_in_epsilon(10.0, ("1."+"1"*300000).to_f*9)
+ end;
+ end
end
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index f04e7e0255..381fcd4d18 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -112,4 +112,18 @@ class TestGc < Test::Unit::TestCase
ObjectSpace.define_finalizer(Thread.main) { p 'finalize' }
EOS
end
+
+ def test_sweep_in_finalizer
+ bug9205 = '[ruby-core:58833] [Bug #9205]'
+ 2.times do
+ assert_ruby_status([], <<-'end;', bug9205)
+ raise_proc = proc do |id|
+ GC.start
+ end
+ 1000.times do
+ ObjectSpace.define_finalizer(Object.new, raise_proc)
+ end
+ end;
+ end
+ end
end
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index 82272cb301..019196bd2e 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -1,5 +1,6 @@
require 'test/unit'
require 'continuation'
+require_relative "envutil"
class TestHash < Test::Unit::TestCase
@@ -116,6 +117,12 @@ class TestHash < Test::Unit::TestCase
end
+ def test_self_initialize_copy
+ h = @cls[1=>2]
+ h.instance_eval {initialize_copy(h)}
+ assert_equal(2, h[1])
+ end
+
def test_AREF # '[]'
t = Time.now
h = @cls[
@@ -144,8 +151,6 @@ class TestHash < Test::Unit::TestCase
assert_equal('nil', h1[nil])
assert_equal(nil, h1['nil'])
assert_equal(:default, h1['koala'])
-
-
end
def test_ASET # '[]='
@@ -920,4 +925,32 @@ class TestHash < Test::Unit::TestCase
assert_not_equal(h.hash, h.invert.hash, feature4262)
end
end
+
+ def test_exception_in_rehash
+ bug9187 = '[ruby-core:58728] [Bug #9187]'
+
+ prepare = <<-EOS
+ class Foo
+ def initialize
+ @raise = false
+ end
+
+ def hash
+ raise if @raise
+ @raise = true
+ return 0
+ end
+ end
+ EOS
+
+ code = <<-EOS
+ h = {Foo.new => true}
+ 10_0000.times do
+ h.rehash rescue nil
+ end
+ GC.start
+ EOS
+
+ assert_no_memory_leak([], prepare, code, bug9187)
+ end
end
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index ad9b80faec..5e3a12c999 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -1094,6 +1094,19 @@ class TestIO < Test::Unit::TestCase
end
end
+ def test_close_read_write_separately
+ bug = '[ruby-list:49598]'
+ (1..10).each do |i|
+ assert_nothing_raised(IOError, "#{bug} trying ##{i}") do
+ IO.popen(EnvUtil.rubybin, "r+") {|f|
+ th = Thread.new {f.close_write}
+ f.close_read
+ th.join
+ }
+ end
+ end
+ end
+
def test_pid
r, w = IO.pipe
assert_equal(nil, r.pid)
@@ -1110,6 +1123,17 @@ class TestIO < Test::Unit::TestCase
assert_raise(IOError) { pipe.pid }
end
+ def tesst_pid_after_close_read
+ pid1 = pid2 = nil
+ IO.popen(["echo", ""], "r+") do |io|
+ pid1 = io.pid
+ io.close_read
+ pid2 = io.pid
+ end
+ assert_not_nil(pid1)
+ assert_equal(pid1, pid2)
+ end
+
def make_tempfile
t = Tempfile.new("test_io")
t.binmode
@@ -2147,4 +2171,77 @@ End
IO.select(tempfiles)
}, bug8080
end
+
+ def test_read_32bit_boundary
+ bug8431 = '[ruby-core:55098] [Bug #8431]'
+ make_tempfile {|t|
+ assert_separately(["-", bug8431, t.path], <<-"end;")
+ msg = ARGV.shift
+ f = open(ARGV[0], "rb")
+ f.seek(0xffff_ffff)
+ assert_nil(f.read(1), msg)
+ end;
+ }
+ end if /mswin|mingw/ =~ RUBY_PLATFORM
+
+ def test_write_32bit_boundary
+ bug8431 = '[ruby-core:55098] [Bug #8431]'
+ make_tempfile {|t|
+ assert_separately(["-", bug8431, t.path], <<-"end;", timeout: 30)
+ msg = ARGV.shift
+ f = open(ARGV[0], "wb")
+ f.seek(0xffff_ffff)
+ begin
+ # this will consume very long time or fail by ENOSPC on a
+ # filesystem which sparse file is not supported
+ f.write('1')
+ rescue SystemCallError
+ else
+ assert_equal(0x1_0000_0000, f.tell, msg)
+ end
+ end;
+ }
+ end if /mswin|mingw/ =~ RUBY_PLATFORM
+
+ def test_read_unlocktmp_ensure
+ bug8669 = '[ruby-core:56121] [Bug #8669]'
+
+ str = ""
+ r, = IO.pipe
+ t = Thread.new { r.read(nil, str) }
+ sleep 0.1 until t.stop?
+ t.raise
+ sleep 0.1 while t.alive?
+ assert_nothing_raised(RuntimeError, bug8669) { str.clear }
+ ensure
+ t.kill
+ end
+
+ def test_readpartial_unlocktmp_ensure
+ bug8669 = '[ruby-core:56121] [Bug #8669]'
+
+ str = ""
+ r, = IO.pipe
+ t = Thread.new { r.readpartial(4096, str) }
+ sleep 0.1 until t.stop?
+ t.raise
+ sleep 0.1 while t.alive?
+ assert_nothing_raised(RuntimeError, bug8669) { str.clear }
+ ensure
+ t.kill
+ end
+
+ def test_sysread_unlocktmp_ensure
+ bug8669 = '[ruby-core:56121] [Bug #8669]'
+
+ str = ""
+ r, = IO.pipe
+ t = Thread.new { r.sysread(4096, str) }
+ sleep 0.1 until t.stop?
+ t.raise
+ sleep 0.1 while t.alive?
+ assert_nothing_raised(RuntimeError, bug8669) { str.clear }
+ ensure
+ t.kill
+ end
end
diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb
index 98c9e2b41c..c22f665286 100644
--- a/test/ruby/test_io_m17n.rb
+++ b/test/ruby/test_io_m17n.rb
@@ -2067,7 +2067,17 @@ EOT
open("a", "wb") {|f| f.puts "a"}
open("a", "rt") {|f| f.getc}
}
- assert(c.ascii_only?, "should be ascii_only #{bug4557}")
+ assert(c.ascii_only?, bug4557)
+ end
+
+ def test_getc_conversion
+ bug8516 = '[ruby-core:55444] [Bug #8516]'
+ c = with_tmpdir {
+ open("a", "wb") {|f| f.putc "\xe1"}
+ open("a", "r:iso-8859-1:utf-8") {|f| f.getc}
+ }
+ refute(c.ascii_only?, bug8516)
+ assert_equal(1, c.size, bug8516)
end
def test_default_mode_on_dosish
diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index 699c8151dd..e92b85dbb8 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -1180,7 +1180,7 @@ class TestM17N < Test::Unit::TestCase
def test_symbol_op
ops = %w"
- .. ... + - +(binary) -(binary) * / % ** +@ -@ | ^ & ! <=> > >= < <= ==
+ .. ... + - * / % ** +@ -@ | ^ & ! <=> > >= < <= ==
=== != =~ !~ ~ ! [] []= << >> :: `
"
ops.each do |op|
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index ea6c5f2164..889c50efbe 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -472,4 +472,18 @@ class TestMethod < Test::Unit::TestCase
1000.times {p = Bug6171.new('test'); 10000.times {p.reverse}}
EOC
end
+
+ def test_gced_bmethod
+ assert_normal_exit %q{
+ require 'irb'
+ IRB::Irb.module_eval do
+ define_method(:eval_input) do
+ IRB::Irb.module_eval { alias_method :eval_input, :to_s }
+ GC.start
+ Kernel
+ end
+ end
+ IRB.start
+ }, '[Bug #7825]'
+ end
end
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 6176f484bc..1fe67df2be 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -277,6 +277,17 @@ class TestModule < Test::Unit::TestCase
assert_equal([:MIXIN, :USER], User.constants.sort)
end
+ def test_self_initialize_copy
+ bug9535 = '[ruby-dev:47989] [Bug #9535]'
+ m = Module.new do
+ def foo
+ :ok
+ end
+ initialize_copy(self)
+ end
+ assert_equal(:ok, Object.new.extend(m).foo, bug9535)
+ end
+
def test_included_modules
assert_equal([], Mixin.included_modules)
assert_equal([Mixin], User.included_modules)
@@ -669,6 +680,19 @@ class TestModule < Test::Unit::TestCase
m.instance_eval { remove_const(:Foo) }
end
+ class Bug9413
+ class << self
+ Foo = :foo
+ end
+ end
+
+ def test_singleton_constants
+ bug9413 = '[ruby-core:59763] [Bug #9413]'
+ c = Bug9413.singleton_class
+ assert_include(c.constants(true), :Foo, bug9413)
+ assert_include(c.constants(false), :Foo, bug9413)
+ end
+
def test_frozen_class
m = Module.new
m.freeze
@@ -1220,4 +1244,24 @@ class TestModule < Test::Unit::TestCase
INPUT
assert_in_out_err([], src, ["NameError"], [])
end
+
+ def test_include_module_with_constants_invalidates_method_cache
+ assert_in_out_err([], <<-RUBY, %w(123 456), [])
+ A = 123
+
+ class Foo
+ def self.a
+ A
+ end
+ end
+
+ module M
+ A = 456
+ end
+
+ puts Foo.a
+ Foo.send(:include, M)
+ puts Foo.a
+ RUBY
+ end
end
diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb
index c862215cb4..52beb9f8d4 100644
--- a/test/ruby/test_pack.rb
+++ b/test/ruby/test_pack.rb
@@ -180,6 +180,7 @@ class TestPack < Test::Unit::TestCase
assert_equal a[0], a.pack("p").unpack("p")[0]
assert_equal a, a.pack("p").freeze.unpack("p*")
assert_raise(ArgumentError) { (a.pack("p") + "").unpack("p*") }
+ assert_raise(ArgumentError) { (a.pack("p") << "d").unpack("p*") }
end
def test_format_string_modified
diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb
index 14990be12c..6de57c1a22 100644
--- a/test/ruby/test_parse.rb
+++ b/test/ruby/test_parse.rb
@@ -358,6 +358,17 @@ class TestParse < Test::Unit::TestCase
assert_equal("foo 1 bar", "foo #$1 bar")
end
+ def test_dstr_disallowd_variable
+ bug8375 = '[ruby-core:54885] [Bug #8375]'
+ %w[@ @1 @@. @@ @@1 @@. $ $%].each do |src|
+ src = '#'+src+' '
+ str = assert_nothing_raised(SyntaxError, "#{bug8375} #{src.dump}") do
+ break eval('"'+src+'"')
+ end
+ assert_equal(src, str, bug8375)
+ end
+ end
+
def test_dsym
assert_nothing_raised { eval(':""') }
end
@@ -524,13 +535,14 @@ class TestParse < Test::Unit::TestCase
)
end
- assert_raise(SyntaxError) do
- eval %q(
+ assert_nothing_raised(SyntaxError) do
+ x = eval %q(
<<FOO
#$
FOO
)
end
+ assert_equal "\#$\n", x
assert_raise(SyntaxError) do
eval %Q(
@@ -550,14 +562,15 @@ FOO
)
end
- assert_raise(SyntaxError) do
- eval %q(
+ assert_nothing_raised(SyntaxError) do
+ x = eval %q(
<<FOO
#$
foo
FOO
)
end
+ assert_equal "\#$\nfoo\n", x
assert_nothing_raised do
eval "x = <<""FOO\r\n1\r\nFOO"
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index 3cac94a100..7560ce94ef 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -1,4 +1,5 @@
require 'test/unit'
+require_relative 'envutil'
class TestProc < Test::Unit::TestCase
def setup
@@ -140,6 +141,14 @@ class TestProc < Test::Unit::TestCase
method(:m2).to_proc
end
+ def m1(var)
+ var
+ end
+
+ def m_block_given?
+ m1(block_given?)
+ end
+
# [yarv-dev:777] block made by Method#to_proc
def test_method_to_proc
b = block()
@@ -147,6 +156,37 @@ class TestProc < Test::Unit::TestCase
assert_instance_of(Binding, b.binding, '[ruby-core:25589]')
end
+ def test_block_given_method
+ m = method(:m_block_given?)
+ assert(!m.call, "without block")
+ assert(m.call {}, "with block")
+ assert(!m.call, "without block second")
+ end
+
+ def test_block_given_method_to_proc
+ bug8341 = '[Bug #8341]'
+ m = method(:m_block_given?).to_proc
+ assert(!m.call, "#{bug8341} without block")
+ assert(m.call {}, "#{bug8341} with block")
+ assert(!m.call, "#{bug8341} without block second")
+ end
+
+ def test_block_persist_between_calls
+ bug8341 = '[Bug #8341]'
+ o = Object.new
+ def o.m1(top=true)
+ if top
+ [block_given?, @m.call(false)]
+ else
+ block_given?
+ end
+ end
+ m = o.method(:m1).to_proc
+ o.instance_variable_set(:@m, m)
+ assert_equal([true, false], m.call {}, "#{bug8341} nested with block")
+ assert_equal([false, false], m.call, "#{bug8341} nested without block")
+ end
+
def test_curry
b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
assert_equal(6, b.curry[1][2][3])
@@ -818,4 +858,14 @@ class TestProc < Test::Unit::TestCase
assert_equal('zot', o.method(:foo).to_proc.() {'zot'}, bug3792)
}
end
+
+ def test_overriden_lambda
+ bug8345 = '[ruby-core:54687] [Bug #8345]'
+ assert_normal_exit('def lambda; end; method(:puts).to_proc', bug8345)
+ end
+
+ def test_overriden_proc
+ bug8345 = '[ruby-core:54688] [Bug #8345]'
+ assert_normal_exit('def proc; end; ->{}.curry', bug8345)
+ end
end
diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index d1e2e1984d..83ff379ca9 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -1319,6 +1319,18 @@ class TestProcess < Test::Unit::TestCase
assert_equal(2, data.size, bug4920)
assert_not_include(data.map(&:to_i), pid)
end
+ else # darwin
+ def test_daemon_no_threads
+ data = Timeout.timeout(3) do
+ IO.popen("-") do |f|
+ break f.readlines.map(&:chomp) if f
+ th = Thread.start {sleep 3}
+ Process.daemon(true, true)
+ puts Thread.list.size, th.status.inspect
+ end
+ end
+ assert_equal(["1", "false"], data)
+ end
end
end
diff --git a/test/ruby/test_sprintf_comb.rb b/test/ruby/test_sprintf_comb.rb
index 261732bcbc..c58ddf4f15 100644
--- a/test/ruby/test_sprintf_comb.rb
+++ b/test/ruby/test_sprintf_comb.rb
@@ -107,7 +107,9 @@ class TestSprintfComb < Test::Unit::TestCase
]
VS.reverse!
- def combination(*args, &b)
+ FLAGS = [['', ' '], ['', '#'], ['', '+'], ['', '-'], ['', '0']]
+
+ def self.combination(*args, &b)
#AllPairs.exhaustive_each(*args, &b)
AllPairs.each(*args, &b)
end
@@ -268,17 +270,8 @@ class TestSprintfComb < Test::Unit::TestCase
str
end
- def test_format_integer
- combination(
- %w[B b d o X x],
- [nil, 0, 5, 20],
- ["", ".", ".0", ".8", ".20"],
- ['', ' '],
- ['', '#'],
- ['', '+'],
- ['', '-'],
- ['', '0']) {|type, width, precision, sp, hs, pl, mi, zr|
- format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
+ def self.assertions_format_integer(format)
+ proc {
VS.each {|v|
r = sprintf format, v
e = emu_int format, v
@@ -293,6 +286,14 @@ class TestSprintfComb < Test::Unit::TestCase
}
end
+ combination(%w[B b d o X x],
+ [nil, 0, 5, 20],
+ ["", ".", ".0", ".8", ".20"],
+ *FLAGS) {|type, width, precision, sp, hs, pl, mi, zr|
+ format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
+ define_method("test_format_integer(#{format})", assertions_format_integer(format))
+ }
+
FLOAT_VALUES = [
-1e100,
-123456789.0,
@@ -526,17 +527,8 @@ class TestSprintfComb < Test::Unit::TestCase
end
- def test_format_float
- combination(
- %w[e E f g G],
- [nil, 0, 5, 20],
- ["", ".", ".0", ".8", ".20", ".200"],
- ['', ' '],
- ['', '#'],
- ['', '+'],
- ['', '-'],
- ['', '0']) {|type, width, precision, sp, hs, pl, mi, zr|
- format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
+ def self.assertions_format_float(format)
+ proc {
FLOAT_VALUES.each {|v|
r = sprintf format, v
e = emu_float format, v
@@ -550,4 +542,12 @@ class TestSprintfComb < Test::Unit::TestCase
}
}
end
+
+ combination(%w[e E f g G],
+ [nil, 0, 5, 20],
+ ["", ".", ".0", ".8", ".20", ".200", ".9999"],
+ *FLAGS) {|type, width, precision, sp, hs, pl, mi, zr|
+ format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
+ define_method("test_format_float(#{format})", assertions_format_float(format))
+ }
end
diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb
index c98f954092..23c50e6778 100644
--- a/test/ruby/test_symbol.rb
+++ b/test/ruby/test_symbol.rb
@@ -33,7 +33,7 @@ class TestSymbol < Test::Unit::TestCase
assert_inspect_evaled(':foo')
assert_inspect_evaled(':foo!')
assert_inspect_evaled(':bar?')
- assert_inspect_evaled(':<<')
+ assert_inspect_evaled(":<<")
assert_inspect_evaled(':>>')
assert_inspect_evaled(':<=')
assert_inspect_evaled(':>=')
@@ -102,6 +102,33 @@ class TestSymbol < Test::Unit::TestCase
assert_raise(ArgumentError) { :foo.to_proc.call }
end
+ def m_block_given?
+ block_given?
+ end
+
+ def m2_block_given?(m = nil)
+ if m
+ [block_given?, m.call(self)]
+ else
+ block_given?
+ end
+ end
+
+ def test_block_given_to_proc
+ bug8531 = '[Bug #8531]'
+ m = :m_block_given?.to_proc
+ assert(!m.call(self), "#{bug8531} without block")
+ assert(m.call(self) {}, "#{bug8531} with block")
+ assert(!m.call(self), "#{bug8531} without block second")
+ end
+
+ def test_block_persist_between_calls
+ bug8531 = '[Bug #8531]'
+ m2 = :m2_block_given?.to_proc
+ assert_equal([true, false], m2.call(self, m2) {}, "#{bug8531} nested with block")
+ assert_equal([false, false], m2.call(self, m2), "#{bug8531} nested without block")
+ end
+
def test_succ
assert_equal(:fop, :foo.succ)
end
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index d924679c7f..a65b567153 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -55,6 +55,11 @@ class TestSyntax < Test::Unit::TestCase
f.close!
end
+ def test_do_block_in_call_args
+ bug9308 = '[ruby-core:59342] [Bug #9308]'
+ assert_valid_syntax("bar def foo; self.each do end end", bug9308)
+ end
+
def test_reserved_method_no_args
bug6403 = '[ruby-dev:45626]'
assert_valid_syntax("def self; :foo; end", __FILE__, bug6403)
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index e8cb3b1722..4d99053b2f 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -710,4 +710,31 @@ class TestThreadGroup < Test::Unit::TestCase
end
assert_in_delta(t1 - t0, 1, 1)
end
+
+ def test_blocking_mutex_unlocked_on_fork
+ bug8433 = '[ruby-core:55102] [Bug #8433]'
+
+ mutex = Mutex.new
+ flag = false
+ mutex.lock
+
+ th = Thread.new do
+ mutex.synchronize do
+ flag = true
+ sleep
+ end
+ end
+
+ Thread.pass until th.stop?
+ mutex.unlock
+
+ pid = Process.fork do
+ exit(mutex.locked?)
+ end
+
+ th.kill
+
+ pid, status = Process.waitpid2(pid)
+ assert_equal(false, status.success?, bug8433)
+ end if Process.respond_to?(:fork)
end
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb
index 961c49432c..03172149ea 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -14,6 +14,20 @@ class TestTime < Test::Unit::TestCase
$VERBOSE = @verbose
end
+ def no_leap_seconds?
+ # 1972-06-30T23:59:60Z is the first leap second.
+ Time.utc(1972, 7, 1, 0, 0, 0) - Time.utc(1972, 6, 30, 23, 59, 59) == 1
+ end
+
+ def get_t2000
+ if no_leap_seconds?
+ # Sat Jan 01 00:00:00 UTC 2000
+ Time.at(946684800).gmtime
+ else
+ Time.utc(2000, 1, 1)
+ end
+ end
+
def test_new
assert_equal(Time.utc(2000,2,10), Time.new(2000,2,10, 11,0,0, 3600*11))
assert_equal(Time.utc(2000,2,10), Time.new(2000,2,9, 13,0,0, -3600*11))
@@ -378,6 +392,15 @@ class TestTime < Test::Unit::TestCase
assert_kind_of(Integer, T2000.hash)
end
+ def test_reinitialize
+ bug8099 = '[ruby-core:53436] [Bug #8099]'
+ t2000 = get_t2000
+ assert_raise(TypeError, bug8099) {
+ t2000.send(:initialize, 2013, 03, 14)
+ }
+ assert_equal(get_t2000, t2000, bug8099)
+ end
+
def test_init_copy
assert_equal(T2000, T2000.dup)
assert_raise(TypeError) do
diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb
index 0bc6ad7059..d79cc8e3f7 100644
--- a/test/rubygems/test_gem_requirement.rb
+++ b/test/rubygems/test_gem_requirement.rb
@@ -37,17 +37,19 @@ class TestGemRequirement < Gem::TestCase
end
def test_parse_bad
- e = assert_raises ArgumentError do
- Gem::Requirement.parse nil
- end
-
- assert_equal 'Illformed requirement [nil]', e.message
+ [
+ nil,
+ '',
+ '! 1',
+ '= junk',
+ '1..2',
+ ].each do |bad|
+ e = assert_raises ArgumentError do
+ Gem::Requirement.parse bad
+ end
- e = assert_raises ArgumentError do
- Gem::Requirement.parse ""
+ assert_equal "Illformed requirement [#{bad.inspect}]", e.message
end
-
- assert_equal 'Illformed requirement [""]', e.message
end
def test_prerelease_eh
diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb
index f578063edc..e543ef8056 100644
--- a/test/rubygems/test_gem_version.rb
+++ b/test/rubygems/test_gem_version.rb
@@ -64,12 +64,18 @@ class TestGemVersion < Gem::TestCase
end
def test_initialize_bad
- ["junk", "1.0\n2.0"].each do |bad|
- e = assert_raises ArgumentError do
+ %W[
+ junk
+ 1.0\n2.0
+ 1..2
+ 1.2\ 3.4
+ 1-2-3
+ ].each do |bad|
+ e = assert_raises ArgumentError, bad do
Gem::Version.new bad
end
- assert_equal "Malformed version number string #{bad}", e.message
+ assert_equal "Malformed version number string #{bad}", e.message, bad
end
end
diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb
index f693a62e4b..548288817f 100644
--- a/test/socket/test_socket.rb
+++ b/test/socket/test_socket.rb
@@ -454,4 +454,75 @@ class TestSocket < Test::Unit::TestCase
ensure
server.close
end
+
+ def test_connect_in_rescue
+ serv = Addrinfo.tcp(nil, 0).listen
+ addr = serv.connect_address
+ begin
+ raise "dummy error"
+ rescue
+ s = addr.connect
+ assert(!s.closed?)
+ end
+ ensure
+ serv.close if serv && !serv.closed?
+ s.close if s && !s.closed?
+ end
+
+ def test_bind_in_rescue
+ begin
+ raise "dummy error"
+ rescue
+ s = Addrinfo.tcp(nil, 0).bind
+ assert(!s.closed?)
+ end
+ ensure
+ s.close if s && !s.closed?
+ end
+
+ def test_listen_in_rescue
+ begin
+ raise "dummy error"
+ rescue
+ s = Addrinfo.tcp(nil, 0).listen
+ assert(!s.closed?)
+ end
+ ensure
+ s.close if s && !s.closed?
+ end
+
+ def test_udp_server_sockets_in_rescue
+ begin
+ raise "dummy error"
+ rescue
+ ss = Socket.udp_server_sockets(0)
+ ss.each {|s|
+ assert(!s.closed?)
+ }
+ end
+ ensure
+ if ss
+ ss.each {|s|
+ s.close if !s.closed?
+ }
+ end
+ end
+
+ def test_tcp_server_sockets_in_rescue
+ begin
+ raise "dummy error"
+ rescue
+ ss = Socket.tcp_server_sockets(0)
+ ss.each {|s|
+ assert(!s.closed?)
+ }
+ end
+ ensure
+ if ss
+ ss.each {|s|
+ s.close if !s.closed?
+ }
+ end
+ end
+
end if defined?(Socket)
diff --git a/test/socket/test_unix.rb b/test/socket/test_unix.rb
index 3559eb8a75..71ca0d78df 100644
--- a/test/socket/test_unix.rb
+++ b/test/socket/test_unix.rb
@@ -5,6 +5,7 @@ end
require "test/unit"
require "tempfile"
+require "timeout"
require "tmpdir"
require "thread"
require "io/nonblock"
@@ -348,6 +349,28 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
s2.close if s2
end
+ def test_dgram_pair_sendrecvmsg_errno_set
+ s1, s2 = to_close = UNIXSocket.pair(Socket::SOCK_DGRAM)
+ pipe = IO.pipe
+ to_close.concat(pipe)
+ set_errno = lambda do
+ begin
+ pipe[0].read_nonblock(1)
+ fail
+ rescue => e
+ assert(IO::WaitReadable === e)
+ end
+ end
+ Timeout.timeout(10) do
+ set_errno.call
+ assert_equal(2, s1.sendmsg("HI"))
+ set_errno.call
+ assert_equal("HI", s2.recvmsg[0])
+ end
+ ensure
+ to_close.each(&:close) if to_close
+ end
+
def test_epipe # [ruby-dev:34619]
s1, s2 = UNIXSocket.pair
s1.shutdown(Socket::SHUT_WR)
diff --git a/test/test_mathn.rb b/test/test_mathn.rb
index f511adb7d5..42a93139fd 100644
--- a/test/test_mathn.rb
+++ b/test/test_mathn.rb
@@ -5,6 +5,102 @@ require_relative 'ruby/envutil'
class TestMathn < Test::Unit::TestCase
def test_power
assert_in_out_err ['-r', 'mathn', '-e', 'a=1**2;!a'], "", [], [], '[ruby-core:25740]'
- assert_in_out_err ['-r', 'mathn', '-e', 'a=(1<<126)**2;!a'], "", [], [], '[ruby-core:25740]'
+ assert_in_out_err ['-r', 'mathn', '-e', 'a=(1 << 126)**2;!a'], "", [], [], '[ruby-core:25740]'
+ end
+
+ def assert_separated_equal(options, expected, actual, message = nil)
+ assert_in_out_err([*options, '-e', "p((#{actual})==(#{expected}))"], "", ["true"], [], message)
+ end
+
+ def test_floor
+ assert_separated_equal(%w[-rmathn], " 2", "( 13/5).floor")
+ assert_separated_equal(%w[-rmathn], " 2", "( 5/2).floor")
+ assert_separated_equal(%w[-rmathn], " 2", "( 12/5).floor")
+ assert_separated_equal(%w[-rmathn], "-3", "(-12/5).floor")
+ assert_separated_equal(%w[-rmathn], "-3", "( -5/2).floor")
+ assert_separated_equal(%w[-rmathn], "-3", "(-13/5).floor")
+
+ assert_separated_equal(%w[-rmathn], " 2", "( 13/5).floor(0)")
+ assert_separated_equal(%w[-rmathn], " 2", "( 5/2).floor(0)")
+ assert_separated_equal(%w[-rmathn], " 2", "( 12/5).floor(0)")
+ assert_separated_equal(%w[-rmathn], "-3", "(-12/5).floor(0)")
+ assert_separated_equal(%w[-rmathn], "-3", "( -5/2).floor(0)")
+ assert_separated_equal(%w[-rmathn], "-3", "(-13/5).floor(0)")
+
+ assert_separated_equal(%w[-rmathn], "( 13/5)", "( 13/5).floor(2)")
+ assert_separated_equal(%w[-rmathn], "( 5/2)", "( 5/2).floor(2)")
+ assert_separated_equal(%w[-rmathn], "( 12/5)", "( 12/5).floor(2)")
+ assert_separated_equal(%w[-rmathn], "(-12/5)", "(-12/5).floor(2)")
+ assert_separated_equal(%w[-rmathn], "( -5/2)", "( -5/2).floor(2)")
+ assert_separated_equal(%w[-rmathn], "(-13/5)", "(-13/5).floor(2)")
+ end
+
+ def test_ceil
+ assert_separated_equal(%w[-rmathn], " 3", "( 13/5).ceil")
+ assert_separated_equal(%w[-rmathn], " 3", "( 5/2).ceil")
+ assert_separated_equal(%w[-rmathn], " 3", "( 12/5).ceil")
+ assert_separated_equal(%w[-rmathn], "-2", "(-12/5).ceil")
+ assert_separated_equal(%w[-rmathn], "-2", "( -5/2).ceil")
+ assert_separated_equal(%w[-rmathn], "-2", "(-13/5).ceil")
+
+ assert_separated_equal(%w[-rmathn], " 3", "( 13/5).ceil(0)")
+ assert_separated_equal(%w[-rmathn], " 3", "( 5/2).ceil(0)")
+ assert_separated_equal(%w[-rmathn], " 3", "( 12/5).ceil(0)")
+ assert_separated_equal(%w[-rmathn], "-2", "(-12/5).ceil(0)")
+ assert_separated_equal(%w[-rmathn], "-2", "( -5/2).ceil(0)")
+ assert_separated_equal(%w[-rmathn], "-2", "(-13/5).ceil(0)")
+
+ assert_separated_equal(%w[-rmathn], "( 13/5)", "( 13/5).ceil(2)")
+ assert_separated_equal(%w[-rmathn], "( 5/2)", "( 5/2).ceil(2)")
+ assert_separated_equal(%w[-rmathn], "( 12/5)", "( 12/5).ceil(2)")
+ assert_separated_equal(%w[-rmathn], "(-12/5)", "(-12/5).ceil(2)")
+ assert_separated_equal(%w[-rmathn], "( -5/2)", "( -5/2).ceil(2)")
+ assert_separated_equal(%w[-rmathn], "(-13/5)", "(-13/5).ceil(2)")
+ end
+
+ def test_truncate
+ assert_separated_equal(%w[-rmathn], " 2", "( 13/5).truncate")
+ assert_separated_equal(%w[-rmathn], " 2", "( 5/2).truncate")
+ assert_separated_equal(%w[-rmathn], " 2", "( 12/5).truncate")
+ assert_separated_equal(%w[-rmathn], "-2", "(-12/5).truncate")
+ assert_separated_equal(%w[-rmathn], "-2", "( -5/2).truncate")
+ assert_separated_equal(%w[-rmathn], "-2", "(-13/5).truncate")
+
+ assert_separated_equal(%w[-rmathn], " 2", "( 13/5).truncate(0)")
+ assert_separated_equal(%w[-rmathn], " 2", "( 5/2).truncate(0)")
+ assert_separated_equal(%w[-rmathn], " 2", "( 12/5).truncate(0)")
+ assert_separated_equal(%w[-rmathn], "-2", "(-12/5).truncate(0)")
+ assert_separated_equal(%w[-rmathn], "-2", "( -5/2).truncate(0)")
+ assert_separated_equal(%w[-rmathn], "-2", "(-13/5).truncate(0)")
+
+ assert_separated_equal(%w[-rmathn], "( 13/5)", "( 13/5).truncate(2)")
+ assert_separated_equal(%w[-rmathn], "( 5/2)", "( 5/2).truncate(2)")
+ assert_separated_equal(%w[-rmathn], "( 12/5)", "( 12/5).truncate(2)")
+ assert_separated_equal(%w[-rmathn], "(-12/5)", "(-12/5).truncate(2)")
+ assert_separated_equal(%w[-rmathn], "( -5/2)", "( -5/2).truncate(2)")
+ assert_separated_equal(%w[-rmathn], "(-13/5)", "(-13/5).truncate(2)")
+ end
+
+ def test_round
+ assert_separated_equal(%w[-rmathn], " 3", "( 13/5).round")
+ assert_separated_equal(%w[-rmathn], " 3", "( 5/2).round")
+ assert_separated_equal(%w[-rmathn], " 2", "( 12/5).round")
+ assert_separated_equal(%w[-rmathn], "-2", "(-12/5).round")
+ assert_separated_equal(%w[-rmathn], "-3", "( -5/2).round")
+ assert_separated_equal(%w[-rmathn], "-3", "(-13/5).round")
+
+ assert_separated_equal(%w[-rmathn], " 3", "( 13/5).round(0)")
+ assert_separated_equal(%w[-rmathn], " 3", "( 5/2).round(0)")
+ assert_separated_equal(%w[-rmathn], " 2", "( 12/5).round(0)")
+ assert_separated_equal(%w[-rmathn], "-2", "(-12/5).round(0)")
+ assert_separated_equal(%w[-rmathn], "-3", "( -5/2).round(0)")
+ assert_separated_equal(%w[-rmathn], "-3", "(-13/5).round(0)")
+
+ assert_separated_equal(%w[-rmathn], "( 13/5)", "( 13/5).round(2)")
+ assert_separated_equal(%w[-rmathn], "( 5/2)", "( 5/2).round(2)")
+ assert_separated_equal(%w[-rmathn], "( 12/5)", "( 12/5).round(2)")
+ assert_separated_equal(%w[-rmathn], "(-12/5)", "(-12/5).round(2)")
+ assert_separated_equal(%w[-rmathn], "( -5/2)", "( -5/2).round(2)")
+ assert_separated_equal(%w[-rmathn], "(-13/5)", "(-13/5).round(2)")
end
end
diff --git a/test/test_tempfile.rb b/test/test_tempfile.rb
index 1462a981f7..c6cbbeeeeb 100644
--- a/test/test_tempfile.rb
+++ b/test/test_tempfile.rb
@@ -206,6 +206,21 @@ puts Tempfile.new('foo').path
end
end
+ def test_tempfile_finalizer_does_not_run_if_unlinked
+ bug8768 = '[ruby-core:56521] [Bug #8768]'
+ args = %w(--disable-gems -rtempfile)
+ assert_in_out_err(args, <<-'EOS') do |(filename), (error)|
+ tmp = Tempfile.new('foo')
+ puts tmp.path
+ tmp.close
+ tmp.unlink
+ $DEBUG = true
+ EOS
+ refute File.exist?(filename)
+ assert_nil(error, "#{bug8768} we used to get a confusing 'removing ...done' here")
+ end
+ end
+
def test_size_flushes_buffer_before_determining_file_size
t = tempfile("foo")
t.write("hello")
diff --git a/test/test_time.rb b/test/test_time.rb
index 9dbce3f654..df6bbfd20c 100644
--- a/test/test_time.rb
+++ b/test/test_time.rb
@@ -393,6 +393,8 @@ class TestTimeExtension < Test::Unit::TestCase # :nodoc:
def test_strptime
assert_equal(Time.utc(2005, 8, 28, 06, 54, 20), Time.strptime("28/Aug/2005:06:54:20 +0000", "%d/%b/%Y:%T %z"))
assert_equal(Time.at(1).localtime, Time.strptime("1", "%s"))
+ assert_equal(false, Time.strptime('0', '%s').utc?)
+ assert_equal(3600, Time.strptime('0 +0100', '%s %z').utc_offset)
end
def test_nsec
diff --git a/test/thread/test_queue.rb b/test/thread/test_queue.rb
index b0ffe0866d..9d8d481ba4 100644
--- a/test/thread/test_queue.rb
+++ b/test/thread/test_queue.rb
@@ -10,6 +10,28 @@ class TestQueue < Test::Unit::TestCase
grind(5, 1000, 15, SizedQueue, 1000)
end
+ def test_sized_queue_clear
+ # Fill queue, then test that SizedQueue#clear wakes up all waiting threads
+ sq = SizedQueue.new(2)
+ 2.times { sq << 1 }
+
+ t1 = Thread.new do
+ sq << 1
+ end
+
+ t2 = Thread.new do
+ sq << 1
+ end
+
+ t3 = Thread.new do
+ Thread.pass
+ sq.clear
+ end
+
+ [t3, t2, t1].each(&:join)
+ assert_equal sq.length, 2
+ end
+
def grind(num_threads, num_objects, num_iterations, klass, *args)
from_workers = klass.new(*args)
to_workers = klass.new(*args)
diff --git a/test/webrick/test_cgi.rb b/test/webrick/test_cgi.rb
index d930c265de..702b8b46bd 100644
--- a/test/webrick/test_cgi.rb
+++ b/test/webrick/test_cgi.rb
@@ -19,7 +19,7 @@ class TestWEBrickCGI < Test::Unit::TestCase
end
},
}
- if RUBY_PLATFORM =~ /mswin32|mingw|cygwin|bccwin32/
+ if RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/
config[:CGIPathEnv] = ENV['PATH'] # runtime dll may not be in system dir.
end
TestWEBrick.start_httpserver(config){|server, addr, port, log|
diff --git a/test/webrick/test_httputils.rb b/test/webrick/test_httputils.rb
index ebe8a2b8a5..2753cbe6c9 100644
--- a/test/webrick/test_httputils.rb
+++ b/test/webrick/test_httputils.rb
@@ -66,6 +66,10 @@ class TestWEBrickHTTPUtils < Test::Unit::TestCase
assert_equal("/~foo%20bar", escape("/~foo bar"))
assert_equal("/~foo%09bar", escape("/~foo\tbar"))
assert_equal("/~foo+bar", escape("/~foo+bar"))
+ bug8425 = '[Bug #8425] [ruby-core:55052]'
+ assert_nothing_raised(ArgumentError, Encoding::CompatibilityError, bug8425) {
+ assert_equal("%E3%83%AB%E3%83%93%E3%83%BC%E3%81%95%E3%82%93", escape("\u{30EB 30D3 30FC 3055 3093}"))
+ }
end
def test_escape_form
diff --git a/thread.c b/thread.c
index 387bf1ff72..ba6a9403b8 100644
--- a/thread.c
+++ b/thread.c
@@ -345,6 +345,8 @@ typedef struct rb_mutex_struct
} rb_mutex_t;
static void rb_mutex_abandon_all(rb_mutex_t *mutexes);
+static void rb_mutex_abandon_keeping_mutexes(rb_thread_t *th);
+static void rb_mutex_abandon_locking_mutex(rb_thread_t *th);
static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th);
void
@@ -3109,10 +3111,8 @@ terminate_atfork_i(st_data_t key, st_data_t val, st_data_t current_th)
GetThreadPtr(thval, th);
if (th != (rb_thread_t *)current_th) {
- if (th->keeping_mutexes) {
- rb_mutex_abandon_all(th->keeping_mutexes);
- }
- th->keeping_mutexes = NULL;
+ rb_mutex_abandon_keeping_mutexes(th);
+ rb_mutex_abandon_locking_mutex(th);
thread_cleanup_func(th, TRUE);
}
return ST_CONTINUE;
@@ -3370,8 +3370,6 @@ thgroup_add(VALUE group, VALUE thread)
#define GetMutexPtr(obj, tobj) \
TypedData_Get_Struct((obj), rb_mutex_t, &mutex_data_type, (tobj))
-static const char *rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th);
-
#define mutex_mark NULL
static void
@@ -3688,6 +3686,28 @@ rb_mutex_unlock(VALUE self)
}
static void
+rb_mutex_abandon_keeping_mutexes(rb_thread_t *th)
+{
+ if (th->keeping_mutexes) {
+ rb_mutex_abandon_all(th->keeping_mutexes);
+ }
+ th->keeping_mutexes = NULL;
+}
+
+static void
+rb_mutex_abandon_locking_mutex(rb_thread_t *th)
+{
+ rb_mutex_t *mutex;
+
+ if (!th->locking_mutex) return;
+
+ GetMutexPtr(th->locking_mutex, mutex);
+ if (mutex->th == th)
+ rb_mutex_abandon_all(mutex);
+ th->locking_mutex = Qfalse;
+}
+
+static void
rb_mutex_abandon_all(rb_mutex_t *mutexes)
{
rb_mutex_t *mutex;
@@ -4376,6 +4396,18 @@ rb_clear_trace_func(void)
static void call_trace_func(rb_event_flag_t, VALUE data, VALUE self, ID id, VALUE klass);
/*
+ * If recursion is detected on the current method, obj and paired_obj,
+ * the outermost func will be called with (obj, arg, Qtrue). All inner
+ * func will be short-circuited using throw.
+ */
+
+VALUE
+rb_exec_recursive_paired_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
+{
+ return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 1);
+}
+
+/*
* call-seq:
* set_trace_func(proc) -> proc
* set_trace_func(nil) -> nil
diff --git a/thread_pthread.c b/thread_pthread.c
index 2cfceef936..9616cc2e38 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -1193,17 +1193,16 @@ rb_thread_create_timer_thread(void)
pthread_attr_init(&attr);
#ifdef PTHREAD_STACK_MIN
- if (PTHREAD_STACK_MIN < 4096 * 3) {
+ {
+ const size_t min_size = (4096 * 4);
/* Allocate the machine stack for the timer thread
- * at least 12KB (3 pages). FreeBSD 8.2 AMD64 causes
- * machine stack overflow only with PTHREAD_STACK_MIN.
+ * at least 16KB (4 pages). FreeBSD 8.2 AMD64 causes
+ * machine stack overflow only with PTHREAD_STACK_MIN.
*/
- pthread_attr_setstacksize(&attr,
- 4096 * 3 + (THREAD_DEBUG ? BUFSIZ : 0));
- }
- else {
- pthread_attr_setstacksize(&attr,
- PTHREAD_STACK_MIN + (THREAD_DEBUG ? BUFSIZ : 0));
+ size_t stack_size = PTHREAD_STACK_MIN; /* may be dynamic, get only once */
+ if (stack_size < min_size) stack_size = min_size;
+ if (THREAD_DEBUG) stack_size += BUFSIZ;
+ pthread_attr_setstacksize(&attr, stack_size);
}
#endif
diff --git a/time.c b/time.c
index 6b6167b40e..6fd36f04de 100644
--- a/time.c
+++ b/time.c
@@ -1809,10 +1809,11 @@ struct time_object {
int tm_got;
};
-#define GetTimeval(obj, tobj) \
- TypedData_Get_Struct((obj), struct time_object, &time_data_type, (tobj))
+#define GetTimeval(obj, tobj) ((tobj) = get_timeval(obj))
+#define GetNewTimeval(obj, tobj) ((tobj) = get_new_timeval(obj))
#define IsTimeval(obj) rb_typeddata_is_kind_of((obj), &time_data_type)
+#define TIME_INIT_P(tobj) ((tobj)->gmt != -1)
#define TIME_UTC_P(tobj) ((tobj)->gmt == 1)
#define TIME_SET_UTC(tobj) ((tobj)->gmt = 1)
@@ -1875,12 +1876,35 @@ time_s_alloc(VALUE klass)
struct time_object *tobj;
obj = TypedData_Make_Struct(klass, struct time_object, &time_data_type, tobj);
+ tobj->gmt = -1;
tobj->tm_got=0;
tobj->timew = WINT2FIXWV(0);
return obj;
}
+static struct time_object *
+get_timeval(VALUE obj)
+{
+ struct time_object *tobj;
+ TypedData_Get_Struct(obj, struct time_object, &time_data_type, tobj);
+ if (!TIME_INIT_P(tobj)) {
+ rb_raise(rb_eTypeError, "uninitialized %"PRIiVALUE, CLASS_OF(obj));
+ }
+ return tobj;
+}
+
+static struct time_object *
+get_new_timeval(VALUE obj)
+{
+ struct time_object *tobj;
+ TypedData_Get_Struct(obj, struct time_object, &time_data_type, tobj);
+ if (TIME_INIT_P(tobj)) {
+ rb_raise(rb_eTypeError, "already initialized %"PRIiVALUE, CLASS_OF(obj));
+ }
+ return tobj;
+}
+
static void
time_modify(VALUE time)
{
@@ -1947,7 +1971,8 @@ time_init_0(VALUE time)
struct timespec ts;
time_modify(time);
- GetTimeval(time, tobj);
+ GetNewTimeval(time, tobj);
+ tobj->gmt = 0;
tobj->tm_got=0;
tobj->timew = WINT2FIXWV(0);
#ifdef HAVE_CLOCK_GETTIME
@@ -2188,7 +2213,8 @@ time_init_1(int argc, VALUE *argv, VALUE time)
validate_vtm(&vtm);
time_modify(time);
- GetTimeval(time, tobj);
+ GetNewTimeval(time, tobj);
+ tobj->gmt = 0;
tobj->tm_got=0;
tobj->timew = WINT2FIXWV(0);
@@ -2304,7 +2330,8 @@ time_new_timew(VALUE klass, wideval_t timew)
VALUE time = time_s_alloc(klass);
struct time_object *tobj;
- GetTimeval(time, tobj);
+ tobj = DATA_PTR(time); /* skip type check */
+ tobj->gmt = 0;
tobj->timew = timew;
return time;
@@ -3430,7 +3457,7 @@ time_init_copy(VALUE copy, VALUE time)
if (copy == time) return copy;
time_modify(copy);
GetTimeval(time, tobj);
- GetTimeval(copy, tcopy);
+ GetNewTimeval(copy, tcopy);
MEMCPY(tcopy, tobj, struct time_object, 1);
return copy;
@@ -4807,7 +4834,8 @@ end_submicro: ;
timew = timegmw(&vtm);
}
- GetTimeval(time, tobj);
+ GetNewTimeval(time, tobj);
+ tobj->gmt = 0;
tobj->tm_got = 0;
tobj->timew = timew;
if (gmt) {
diff --git a/tool/mkconfig.rb b/tool/mkconfig.rb
index 6d8751175e..bddf381d67 100755
--- a/tool/mkconfig.rb
+++ b/tool/mkconfig.rb
@@ -62,6 +62,7 @@ File.foreach "config.status" do |line|
next if !continued_line
continued_line << $1
next if $2
+ continued_line.each {|s| s.sub!(/\\n\z/, "\n")}
val = continued_line.join
name = continued_name
continued_line = nil
diff --git a/util.c b/util.c
index 45493f2855..2b8209d9da 100644
--- a/util.c
+++ b/util.c
@@ -278,7 +278,9 @@ ruby_qsort(void* base, const size_t nel, const size_t size,
char *L = base; /* left end of current region */
char *R = (char*)base + size*(nel-1); /* right end of current region */
size_t chklim = 63; /* threshold of ordering element check */
- stack_node stack[32], *top = stack; /* 32 is enough for 32bit CPU */
+ enum {size_bits = sizeof(size) * CHAR_BIT};
+ stack_node stack[size_bits]; /* enough for size_t size */
+ stack_node *top = stack;
int mmkind;
size_t high, low, n;
@@ -674,6 +676,11 @@ extern void *MALLOC(size_t);
#else
#define MALLOC malloc
#endif
+#ifdef FREE
+extern void FREE(void*);
+#else
+#define FREE free
+#endif
#ifndef Omit_Private_Memory
#ifndef PRIVATE_MEM
@@ -964,7 +971,7 @@ Balloc(int k)
#endif
ACQUIRE_DTOA_LOCK(0);
- if ((rv = freelist[k]) != 0) {
+ if (k <= Kmax && (rv = freelist[k]) != 0) {
freelist[k] = rv->next;
}
else {
@@ -974,7 +981,7 @@ Balloc(int k)
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double);
- if (pmem_next - private_mem + len <= PRIVATE_mem) {
+ if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
rv = (Bigint*)pmem_next;
pmem_next += len;
}
@@ -993,6 +1000,10 @@ static void
Bfree(Bigint *v)
{
if (v) {
+ if (v->k > Kmax) {
+ FREE(v);
+ return;
+ }
ACQUIRE_DTOA_LOCK(0);
v->next = freelist[v->k];
freelist[v->k] = v;
@@ -2053,6 +2064,7 @@ break2:
for (; c >= '0' && c <= '9'; c = *++s) {
have_dig:
nz++;
+ if (nf > DBL_DIG * 4) continue;
if (c -= '0') {
nf += nz;
for (i = 1; i < nz; i++)
diff --git a/version.h b/version.h
index 42b30cc0e2..aa87e82662 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 415
+#define RUBY_PATCHLEVEL 546
-#define RUBY_RELEASE_DATE "2013-04-11"
-#define RUBY_RELEASE_YEAR 2013
-#define RUBY_RELEASE_MONTH 4
-#define RUBY_RELEASE_DAY 11
+#define RUBY_RELEASE_DATE "2014-03-31"
+#define RUBY_RELEASE_YEAR 2014
+#define RUBY_RELEASE_MONTH 3
+#define RUBY_RELEASE_DAY 31
#include "ruby/version.h"
diff --git a/vm.c b/vm.c
index 6b2bd907ff..ab614c327d 100644
--- a/vm.c
+++ b/vm.c
@@ -1744,7 +1744,11 @@ rb_thread_mark(void *ptr)
if (iseq) {
rb_gc_mark(RUBY_VM_NORMAL_ISEQ_P(iseq) ? iseq->self : (VALUE)iseq);
}
- if (cfp->me) ((rb_method_entry_t *)cfp->me)->mark = 1;
+ if (cfp->me) {
+ /* TODO: marking `me' can be more sophisticated way */
+ ((rb_method_entry_t *)cfp->me)->mark = 1;
+ rb_mark_method_entry(cfp->me);
+ }
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
}
@@ -2109,6 +2113,8 @@ Init_VM(void)
rb_define_method_id(klass, id_core_define_method, m_core_define_method, 3);
rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3);
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 1);
+ rb_define_method_id(klass, idProc, rb_block_proc, 0);
+ rb_define_method_id(klass, idLambda, rb_block_lambda, 0);
rb_obj_freeze(fcore);
rb_gc_register_mark_object(fcore);
rb_mRubyVMFrozenCore = fcore;
diff --git a/vm_eval.c b/vm_eval.c
index 0c740285be..2291001a2e 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -694,6 +694,23 @@ rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
}
+VALUE
+rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE pass_procval)
+{
+ if (!NIL_P(pass_procval)) {
+ rb_thread_t *th = GET_THREAD();
+ rb_block_t *block = 0;
+
+ rb_proc_t *pass_proc;
+ GetProcPtr(pass_procval, pass_proc);
+ block = &pass_proc->block;
+
+ th->passed_block = block;
+ }
+
+ return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
+}
+
static VALUE
send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
{
diff --git a/vsnprintf.c b/vsnprintf.c
index 79bde9f485..214b2c639a 100644
--- a/vsnprintf.c
+++ b/vsnprintf.c
@@ -489,14 +489,19 @@ BSD__ultoa(register u_long val, char *endp, int base, int octzero, const char *x
#ifdef FLOATING_POINT
#include <math.h>
+#include <float.h>
/* #include "floatio.h" */
#ifndef MAXEXP
-# define MAXEXP 1024
+# if DBL_MAX_10_EXP > -DBL_MIN_10_EXP
+# define MAXEXP (DBL_MAX_10_EXP)
+# else
+# define MAXEXP (-DBL_MIN_10_EXP)
+# endif
#endif
#ifndef MAXFRACT
-# define MAXFRACT 64
+# define MAXFRACT (MAXEXP*10/3)
#endif
#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
@@ -547,6 +552,7 @@ BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap)
int expt; /* integer value of exponent */
int expsize = 0; /* character count for expstr */
int ndig = 0; /* actual number of digits returned by cvt */
+ int fprec = 0; /* floating point precision */
char expstr[7]; /* buffer for exponent string */
#endif
u_long UNINITIALIZED_VAR(ulval); /* integer arguments %[diouxX] */
@@ -813,6 +819,7 @@ reswitch: switch (ch) {
if (prec > 0) {
flags |= ALT;
prec++;
+ fprec = prec;
}
goto fp_begin;
case 'e': /* anomalous precision */
@@ -820,7 +827,7 @@ reswitch: switch (ch) {
if (prec != 0)
flags |= ALT;
prec = (prec == -1) ?
- DEFPREC + 1 : prec + 1;
+ DEFPREC + 1 : (fprec = prec + 1);
/* FALLTHROUGH */
goto fp_begin;
case 'f': /* always print trailing zeroes */
@@ -830,6 +837,8 @@ reswitch: switch (ch) {
case 'G':
if (prec == -1)
prec = DEFPREC;
+ else
+ fprec = prec;
fp_begin: _double = va_arg(ap, double);
/* do this before tricky precision changes */
if (isinf(_double)) {
@@ -845,7 +854,7 @@ fp_begin: _double = va_arg(ap, double);
break;
}
flags |= FPT;
- cp = cvt(_double, prec, flags, &softsign,
+ cp = cvt(_double, (prec < MAXFRACT ? prec : MAXFRACT), flags, &softsign,
&expt, ch, &ndig, buf);
if (ch == 'g' || ch == 'G') {
if (expt <= -4 || (expt > prec && expt > 1))
@@ -867,7 +876,7 @@ fp_begin: _double = va_arg(ap, double);
expsize = exponent(expstr, expt, ch);
size = expsize + ndig;
if (ndig > 1 || flags & ALT)
- ++size;
+ ++fprec, ++size;
} else if (ch == 'f') { /* f fmt */
if (expt > 0) {
size = expt;
@@ -1099,6 +1108,7 @@ long_len:
if (ndig > 0) PRINT(cp, ndig-1);
} else /* XpYYY */
PRINT(cp, 1);
+ PAD(fprec-ndig, zeroes);
PRINT(expstr, expsize);
}
else if (ch >= 'f') { /* 'f' or 'g' */
@@ -1109,7 +1119,8 @@ long_len:
PRINT("0", 1);
} else {
PRINT("0.", 2);
- PAD(ndig - 1, zeroes);
+ PAD((ndig >= fprec ? ndig - 1 : fprec - (ch != 'f')),
+ zeroes);
}
} else if (expt == 0 && ndig == 0 && (flags & ALT) == 0) {
PRINT("0", 1);
@@ -1117,6 +1128,8 @@ long_len:
PRINT("0.", 2);
PAD(-expt, zeroes);
PRINT(cp, ndig);
+ if (flags & ALT)
+ PAD(fprec - ndig + (ch == 'f' ? expt : 0), zeroes);
} else if (expt >= ndig) {
PRINT(cp, ndig);
PAD(expt - ndig, zeroes);
@@ -1127,6 +1140,8 @@ long_len:
cp += expt;
PRINT(".", 1);
PRINT(cp, ndig-expt);
+ if (flags & ALT)
+ PAD(fprec - ndig + (ch == 'f' ? expt : 0), zeroes);
}
} else { /* 'e' or 'E' */
if (ndig > 1 || flags & ALT) {
@@ -1138,6 +1153,7 @@ long_len:
} else /* 0.[0..] */
/* __dtoa irregularity */
PAD(ndig - 1, zeroes);
+ if (flags & ALT) PAD(fprec - ndig - 1, zeroes);
} else /* XeYYY */
PRINT(cp, 1);
PRINT(expstr, expsize);
@@ -1222,7 +1238,7 @@ exponent(p0, exp, fmtch)
int exp, fmtch;
{
register char *p, *t;
- char expbuf[MAXEXP];
+ char expbuf[2 + (MAXEXP < 1000 ? 3 : MAXEXP < 10000 ? 4 : 5)]; /* >= 2 + ceil(log10(MAXEXP)) */
p = p0;
*p++ = fmtch;
@@ -1232,13 +1248,13 @@ exponent(p0, exp, fmtch)
}
else
*p++ = '+';
- t = expbuf + MAXEXP;
+ t = expbuf + sizeof(expbuf);
if (exp > 9) {
do {
*--t = to_char(exp % 10);
} while ((exp /= 10) > 9);
*--t = to_char(exp);
- for (; t < expbuf + MAXEXP; *p++ = *t++);
+ for (; t < expbuf + sizeof(expbuf); *p++ = *t++);
}
else {
if (fmtch & 15) *p++ = '0'; /* other than p or P */
diff --git a/win32/Makefile.sub b/win32/Makefile.sub
index 135c2dbcac..15a0f638c7 100644
--- a/win32/Makefile.sub
+++ b/win32/Makefile.sub
@@ -229,7 +229,10 @@ LIBS = oldnames.lib user32.lib advapi32.lib shell32.lib ws2_32.lib imagehlp.lib
LIBS = unicows.lib $(LIBS)
!endif
!if !defined(MISSING)
-MISSING = acosh.obj cbrt.obj crypt.obj erf.obj ffs.obj langinfo.obj lgamma_r.obj strlcat.obj strlcpy.obj tgamma.obj win32/win32.obj win32/file.obj setproctitle.obj
+MISSING = crypt.obj ffs.obj langinfo.obj lgamma_r.obj strlcat.obj strlcpy.obj win32/win32.obj win32/file.obj setproctitle.obj
+!if $(RT_VER) < 120
+MISSING = $(MISSING) acosh.obj cbrt.obj erf.obj tgamma.obj
+!endif
!endif
ARFLAGS = -machine:$(MACHINE) -out:
@@ -597,6 +600,18 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
#define GETGROUPS_T int
#define RETSIGTYPE void
#define TYPEOF_TIMEVAL_TV_SEC long
+!if $(RT_VER) >= 120
+#define HAVE_ACOSH 1
+#define HAVE_ASINH 1
+#define HAVE_ATANH 1
+#define HAVE_CBRT 1
+#define HAVE_LOG2 1
+#define log2(x) log2(x)
+#define HAVE_ERF 1
+#define HAVE_ERFC 1
+#define HAVE_ROUND 1
+#define HAVE_TGAMMA 1
+!endif
#define HAVE_ALLOCA 1
#define HAVE_DUP2 1
#define HAVE_MEMCMP 1
diff --git a/win32/win32.c b/win32/win32.c
index c35e5462f8..e04edccd8a 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4023,18 +4023,18 @@ wrename(const WCHAR *oldpath, const WCHAR *newpath)
if (newatts != -1 && newatts & FILE_ATTRIBUTE_READONLY)
SetFileAttributesW(newpath, newatts & ~ FILE_ATTRIBUTE_READONLY);
- if (!MoveFileW(oldpath, newpath))
- res = -1;
-
- if (res) {
- switch (GetLastError()) {
- case ERROR_ALREADY_EXISTS:
- case ERROR_FILE_EXISTS:
- if (IsWinNT()) {
- if (MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
- res = 0;
- }
- else {
+ if (IsWinNT()) {
+ if (!MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
+ res = -1;
+ }
+ else {
+ if (!MoveFileW(oldpath, newpath))
+ res = -1;
+
+ if (res) {
+ switch (GetLastError()) {
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_FILE_EXISTS:
for (;;) {
if (!DeleteFileW(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND)
break;
@@ -5180,6 +5180,49 @@ rb_w32_close(int fd)
return 0;
}
+static int
+setup_overlapped(OVERLAPPED *ol, int fd)
+{
+ memset(ol, 0, sizeof(*ol));
+ if (!(_osfile(fd) & (FDEV | FPIPE))) {
+ LONG high = 0;
+ DWORD method = _osfile(fd) & FAPPEND ? FILE_END : FILE_CURRENT;
+ DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high, method);
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+ if (low == INVALID_SET_FILE_POINTER) {
+ DWORD err = GetLastError();
+ if (err != NO_ERROR) {
+ errno = map_errno(err);
+ return -1;
+ }
+ }
+ ol->Offset = low;
+ ol->OffsetHigh = high;
+ }
+ ol->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+ if (!ol->hEvent) {
+ errno = map_errno(GetLastError());
+ return -1;
+ }
+ return 0;
+}
+
+static void
+finish_overlapped(OVERLAPPED *ol, int fd, DWORD size)
+{
+ CloseHandle(ol->hEvent);
+
+ if (!(_osfile(fd) & (FDEV | FPIPE))) {
+ LONG high = ol->OffsetHigh;
+ DWORD low = ol->Offset + size;
+ if (low < ol->Offset)
+ ++high;
+ SetFilePointer((HANDLE)_osfhnd(fd), low, &high, FILE_BEGIN);
+ }
+}
+
#undef read
ssize_t
rb_w32_read(int fd, void *buf, size_t size)
@@ -5238,25 +5281,7 @@ rb_w32_read(int fd, void *buf, size_t size)
/* if have cancel_io, use Overlapped I/O */
if (cancel_io) {
- memset(&ol, 0, sizeof(ol));
- if (!(_osfile(fd) & (FDEV | FPIPE))) {
- LONG high = 0;
- DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high,
- FILE_CURRENT);
-#ifndef INVALID_SET_FILE_POINTER
-#define INVALID_SET_FILE_POINTER ((DWORD)-1)
-#endif
- if (low == INVALID_SET_FILE_POINTER) {
- errno = map_errno(GetLastError());
- MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
- return -1;
- }
- ol.Offset = low;
- ol.OffsetHigh = high;
- }
- ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
- if (!ol.hEvent) {
- errno = map_errno(GetLastError());
+ if (setup_overlapped(&ol, fd)) {
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
return -1;
}
@@ -5310,15 +5335,7 @@ rb_w32_read(int fd, void *buf, size_t size)
}
if (pol) {
- CloseHandle(ol.hEvent);
-
- if (!(_osfile(fd) & (FDEV | FPIPE))) {
- LONG high = ol.OffsetHigh;
- DWORD low = ol.Offset + read;
- if (low < ol.Offset)
- ++high;
- SetFilePointer((HANDLE)_osfhnd(fd), low, &high, FILE_BEGIN);
- }
+ finish_overlapped(&ol, fd, read);
}
ret += read;
@@ -5376,25 +5393,7 @@ rb_w32_write(int fd, const void *buf, size_t size)
/* if have cancel_io, use Overlapped I/O */
if (cancel_io) {
- memset(&ol, 0, sizeof(ol));
- if (!(_osfile(fd) & (FDEV | FPIPE))) {
- LONG high = 0;
- DWORD method = _osfile(fd) & FAPPEND ? FILE_END : FILE_CURRENT;
- DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high, method);
-#ifndef INVALID_SET_FILE_POINTER
-#define INVALID_SET_FILE_POINTER ((DWORD)-1)
-#endif
- if (low == INVALID_SET_FILE_POINTER) {
- errno = map_errno(GetLastError());
- MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
- return -1;
- }
- ol.Offset = low;
- ol.OffsetHigh = high;
- }
- ol.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
- if (!ol.hEvent) {
- errno = map_errno(GetLastError());
+ if (setup_overlapped(&ol, fd)) {
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
return -1;
}
@@ -5440,15 +5439,7 @@ rb_w32_write(int fd, const void *buf, size_t size)
}
if (pol) {
- CloseHandle(ol.hEvent);
-
- if (!(_osfile(fd) & (FDEV | FPIPE))) {
- LONG high = ol.OffsetHigh;
- DWORD low = ol.Offset + written;
- if (low < ol.Offset)
- ++high;
- SetFilePointer((HANDLE)_osfhnd(fd), low, &high, FILE_BEGIN);
- }
+ finish_overlapped(&ol, fd, written);
}
ret += written;