diff options
author | Paul Sherwood <paul.sherwood@codethink.co.uk> | 2014-04-20 09:01:04 +0000 |
---|---|---|
committer | Paul Sherwood <paul.sherwood@codethink.co.uk> | 2014-04-20 09:01:04 +0000 |
commit | 6ecf40e1fa1b2c55f63d0ccb46bce2fca73b40ad (patch) | |
tree | 368a0326bcf36bc7e06cbbe7a1d55b752afd86ba | |
parent | cb3ea602294b5038b5f7ac21d3875a2b52342956 (diff) | |
parent | 680d09b61ea7d850e27944311723a40c596e5d95 (diff) | |
download | ruby-baserock/ps/proto-web-system.tar.gz |
Merge commit '680d09' into baserock/ps/proto-web-systembaserock/ps/proto-web-system
167 files changed, 3780 insertions, 837 deletions
@@ -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 @@ -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 @@ -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--) { @@ -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); } @@ -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 \ @@ -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)); } /* @@ -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); @@ -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 @@ -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); } @@ -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 { @@ -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); @@ -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); @@ -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, '&') str.gsub!(/\"/n, '"') str.gsub!(/>/n, '>') str.gsub!(/</n, '<') - 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 @@ -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) @@ -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) { @@ -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) @@ -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, "e->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; @@ -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); @@ -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); @@ -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 */ @@ -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__) @@ -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) { @@ -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 @@ -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 @@ -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 @@ -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++) @@ -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" @@ -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; @@ -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; |