[ruby/strscan] jruby: Check if len++ walked off the end
[ruby.git] / array.c
diff --git a/array.c b/array.c
index d4b9b87..59fc342 100644 (file)
--- a/array.c
+++ b/array.c
@@ -27,6 +27,7 @@
 #include "probes.h"
 #include "ruby/encoding.h"
 #include "ruby/st.h"
+#include "ruby/thread.h"
 #include "ruby/util.h"
 #include "vm_core.h"
 #include "builtin.h"
@@ -263,12 +264,6 @@ ary_verify_(VALUE ary, const char *file, int line)
 
     return ary;
 }
-
-void
-rb_ary_verify(VALUE ary)
-{
-    ary_verify(ary);
-}
 #else
 #define ary_verify(ary) ((void)0)
 #endif
@@ -527,6 +522,8 @@ rb_ary_set_shared(VALUE ary, VALUE shared_root)
 static inline void
 rb_ary_modify_check(VALUE ary)
 {
+    RUBY_ASSERT(ruby_thread_has_gvl_p());
+
     rb_check_frozen(ary);
     ary_verify(ary);
 }
@@ -711,6 +708,8 @@ empty_ary_alloc(VALUE klass)
 static VALUE
 ary_new(VALUE klass, long capa)
 {
+    RUBY_ASSERT(ruby_thread_has_gvl_p());
+
     VALUE ary;
 
     if (capa < 0) {
@@ -1815,7 +1814,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
  *  If +index+ is out of range, returns +nil+.
  *
  *  When two Integer arguments +start+ and +length+ are given,
- *  returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
+ *  returns a new array of size +length+ containing successive elements beginning at offset +start+:
  *
  *    a = [:foo, 'bar', 2]
  *    a[0, 2] # => [:foo, "bar"]
@@ -1830,7 +1829,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
  *    a[2, 2] # => [2]
  *
  *  If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
- *  returns a new empty +Array+.
+ *  returns a new empty array.
  *
  *  If +length+ is negative, returns +nil+.
  *
@@ -1842,7 +1841,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
  *    a[0..1] # => [:foo, "bar"]
  *    a[1..2] # => ["bar", 2]
  *
- *  Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
+ *  Special case: If <tt>range.start == a.size</tt>, returns a new empty array.
  *
  *  If <tt>range.end</tt> is negative, calculates the end index from the end:
  *
@@ -1866,7 +1865,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
  *    a[4..-1] # => nil
  *
  *  When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
- *  returns an +Array+ of elements corresponding to the indexes produced by
+ *  returns an array of elements corresponding to the indexes produced by
  *  the sequence.
  *
  *    a = ['--', 'data1', '--', 'data2', '--', 'data3']
@@ -2304,7 +2303,7 @@ rb_ary_resize(VALUE ary, long len)
         rb_raise(rb_eIndexError, "index %ld too big", len);
     }
     if (len > olen) {
-        if (len >= ARY_CAPA(ary)) {
+        if (len > ARY_CAPA(ary)) {
             ary_double_capa(ary, len);
         }
         ary_mem_clear(ary, olen, len - olen);
@@ -2408,7 +2407,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
  *    a[-1] = 'two' # => "two"
  *    a # => [:foo, "bar", "two"]
  *
- *  When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
+ *  When Integer arguments +start+ and +length+ are given and +object+ is not an array,
  *  removes <tt>length - 1</tt> elements beginning at offset +start+,
  *  and assigns +object+ at offset +start+:
  *
@@ -2443,7 +2442,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
  *    a[1, 5] = 'foo' # => "foo"
  *    a # => [:foo, "foo"]
  *
- *  When Range argument +range+ is given and +object+ is not an +Array+,
+ *  When Range argument +range+ is given and +object+ is not an array,
  *  removes <tt>length - 1</tt> elements beginning at offset +start+,
  *  and assigns +object+ at offset +start+:
  *
@@ -2759,7 +2758,7 @@ rb_ary_length(VALUE ary)
 
 /*
  *  call-seq:
- *    array.empty?  -> true or false
+ *    empty?  -> true or false
  *
  *  Returns +true+ if the count of elements in +self+ is zero,
  *  +false+ otherwise.
@@ -2928,7 +2927,7 @@ rb_ary_join(VALUE ary, VALUE sep)
 
 /*
  *  call-seq:
- *    array.join(separator = $,) -> new_string
+ *    join(separator = $,) -> new_string
  *
  *  Returns the new string formed by joining the converted elements of +self+;
  *  for each element +element+:
@@ -3019,7 +3018,7 @@ rb_ary_to_s(VALUE ary)
  *  call-seq:
  *    to_a -> self or new_array
  *
- *  When +self+ is an instance of +Array+, returns +self+.
+ *  When +self+ is an instance of \Array, returns +self+.
  *
  *  Otherwise, returns a new array containing the elements of +self+:
  *
@@ -3094,7 +3093,7 @@ rb_ary_to_h(VALUE ary)
 
 /*
  *  call-seq:
- *    array.to_ary -> self
+ *    to_ary -> self
  *
  *  Returns +self+.
  */
@@ -3480,6 +3479,9 @@ rb_ary_sort_bang(VALUE ary)
  *  When the block returns zero, the order for +a+ and +b+ is indeterminate,
  *  and may be unstable.
  *
+ *  See an example in Numeric#nonzero? for the idiom to sort more
+ *  complex structure.
+ *
  *  Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
  */
 
@@ -3613,8 +3615,10 @@ rb_ary_sort_by_bang(VALUE ary)
 
     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
     rb_ary_modify(ary);
-    sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
-    rb_ary_replace(ary, sorted);
+    if (RARRAY_LEN(ary) > 1) {
+        sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
+        rb_ary_replace(ary, sorted);
+    }
     return ary;
 }
 
@@ -4470,7 +4474,7 @@ take_items(VALUE obj, long n)
 /*
  *  call-seq:
  *    zip(*other_arrays) -> new_array
- *    zip(*other_arrays) {|other_array| ... } -> nil
+ *    zip(*other_arrays) {|sub_array| ... } -> nil
  *
  *  With no block given, combines +self+ with the collection of +other_arrays+;
  *  returns a new array of sub-arrays:
@@ -5090,7 +5094,7 @@ rb_ary_concat(VALUE x, VALUE y)
  *  When string argument +string_separator+ is given,
  *  equivalent to <tt>self.join(string_separator)</tt>:
  *
- *    [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
+ *    [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
  *
  */
 
@@ -5317,8 +5321,8 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
     return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
 }
 
-VALUE
-rb_ary_hash_values(long len, const VALUE *elements)
+static VALUE
+ary_hash_values(long len, const VALUE *elements, const VALUE ary)
 {
     long i;
     st_index_t h;
@@ -5329,11 +5333,21 @@ rb_ary_hash_values(long len, const VALUE *elements)
     for (i=0; i<len; i++) {
         n = rb_hash(elements[i]);
         h = rb_hash_uint(h, NUM2LONG(n));
+        if (ary) {
+            len = RARRAY_LEN(ary);
+            elements = RARRAY_CONST_PTR(ary);
+        }
     }
     h = rb_hash_end(h);
     return ST2FIX(h);
 }
 
+VALUE
+rb_ary_hash_values(long len, const VALUE *elements)
+{
+    return ary_hash_values(len, elements, 0);
+}
+
 /*
  *  call-seq:
  *    hash -> integer
@@ -5352,7 +5366,8 @@ rb_ary_hash_values(long len, const VALUE *elements)
 static VALUE
 rb_ary_hash(VALUE ary)
 {
-    return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
+    RBIMPL_ASSERT_OR_ASSUME(ary);
+    return ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), ary);
 }
 
 /*
@@ -5609,7 +5624,7 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
         VALUE elt = rb_ary_elt(ary, i);
         for (j = 0; j < argc; j++) {
             if (is_hash[j]) {
-                if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
+                if (rb_hash_stlike_lookup(argv[j], elt, NULL))
                     break;
             }
             else {
@@ -5979,9 +5994,9 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
 /*
  *  call-seq:
  *    max -> element
- *    max(n) -> new_array
+ *    max(count) -> new_array
  *    max {|a, b| ... } -> element
- *    max(n) {|a, b| ... } -> new_array
+ *    max(count) {|a, b| ... } -> new_array
  *
  *  Returns one of the following:
  *
@@ -5998,8 +6013,8 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
  *
  *    [1, 0, 3, 2].max # => 3
  *
- *  With non-negative numeric argument +n+ and no block,
- *  returns a new array with at most +n+ elements,
+ *  With non-negative numeric argument +count+ and no block,
+ *  returns a new array with at most +count+ elements,
  *  in descending order, per method <tt>#<=></tt>:
  *
  *    [1, 0, 3, 2].max(3)   # => [3, 2, 1]
@@ -6015,8 +6030,8 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
  *    ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
  *    # => "000"
  *
- *  With non-negative numeric argument +n+ and a block,
- *  returns a new array with at most +n+ elements,
+ *  With non-negative numeric argument +count+ and a block,
+ *  returns a new array with at most +count+ elements,
  *  in descending order, per the block:
  *
  *    ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
@@ -6156,9 +6171,9 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
 /*
  *  call-seq:
  *    min -> element
- *    min(n) -> new_array
+ *    min(count) -> new_array
  *    min {|a, b| ... } -> element
- *    min(n) {|a, b| ... } -> new_array
+ *    min(count) {|a, b| ... } -> new_array
  *
  *  Returns one of the following:
  *
@@ -6175,8 +6190,8 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
  *
  *    [1, 0, 3, 2].min # => 0
  *
- *  With non-negative numeric argument +n+ and no block,
- *  returns a new array with at most +n+ elements,
+ *  With non-negative numeric argument +count+ and no block,
+ *  returns a new array with at most +count+ elements,
  *  in ascending order, per method <tt>#<=></tt>:
  *
  *    [1, 0, 3, 2].min(3)   # => [0, 1, 2]
@@ -6192,8 +6207,8 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
  *    ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
  *    # => ""
  *
- *  With non-negative numeric argument +n+ and a block,
- *  returns a new array with at most +n+ elements,
+ *  With non-negative numeric argument +count+ and a block,
+ *  returns a new array with at most +count+ elements,
  *  in ascending order, per the block:
  *
  *    ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
@@ -6707,7 +6722,7 @@ rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
     rb_ary_modify(ary);
     i = len = RARRAY_LEN(ary);
     RARRAY_PTR_USE(ary, ptr, {
-        while (i) {
+        while (i > 1) {
             long j = RAND_UPTO(i);
             VALUE tmp;
             if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
@@ -7069,14 +7084,14 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
 
 /*
  *  call-seq:
- *    permutation(n = self.size) {|permutation| ... } -> self
- *    permutation(n = self.size) -> new_enumerator
+ *    permutation(count = self.size) {|permutation| ... } -> self
+ *    permutation(count = self.size) -> new_enumerator
  *
  *  Iterates over permutations of the elements of +self+;
  *  the order of permutations is indeterminate.
  *
- *  With a block and an in-range positive integer argument +n+ (<tt>0 < n <= self.size</tt>) given,
- *  calls the block with each +n+-tuple permutations of +self+;
+ *  With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
+ *  calls the block with each permutation of +self+ of size +count+;
  *  returns +self+:
  *
  *    a = [0, 1, 2]
@@ -7092,13 +7107,13 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
  *    a.permutation(3) {|perm| perms.push(perm) }
  *    perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
  *
- *  When +n+ is zero, calls the block once with a new empty array:
+ *  When +count+ is zero, calls the block once with a new empty array:
  *
  *    perms = []
  *    a.permutation(0) {|perm| perms.push(perm) }
  *    perms # => [[]]
  *
- *  When +n+ is out of range (negative or larger than <tt>self.size</tt>),
+ *  When +count+ is out of range (negative or larger than <tt>self.size</tt>),
  *  does not call the block:
  *
  *    a.permutation(-1) {|permutation| fail 'Cannot happen' }
@@ -7179,13 +7194,13 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
 
 /*
  *  call-seq:
- *    combination(n) {|element| ... } -> self
- *    combination(n) -> new_enumerator
+ *    combination(count) {|element| ... } -> self
+ *    combination(count) -> new_enumerator
  *
  *  When a block and a positive
  *  {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
- *  argument +n+ (<tt>0 < n <= self.size</tt>)
- *  are given, calls the block with all +n+-tuple combinations of +self+;
+ *  argument +count+ (<tt>0 < count <= self.size</tt>)
+ *  are given, calls the block with each combination of +self+ of size +count+;
  *  returns +self+:
  *
  *    a = %w[a b c]                                   # => ["a", "b", "c"]
@@ -7199,7 +7214,7 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
  *
  *  The order of the yielded combinations is not guaranteed.
  *
- *  When +n+ is zero, calls the block once with a new empty array:
+ *  When +count+ is zero, calls the block once with a new empty array:
  *
  *    a.combination(0) {|combination| p combination }
  *    [].combination(0) {|combination| p combination }
@@ -7209,7 +7224,7 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
  *    []
  *    []
  *
- *  When +n+ is negative or larger than +self.size+ and +self+ is non-empty,
+ *  When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
  *  does not call the block:
  *
  *    a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
@@ -7686,10 +7701,10 @@ rb_ary_take_while(VALUE ary)
 
 /*
  *  call-seq:
- *    drop(n) -> new_array
+ *    drop(count) -> new_array
  *
- *  Returns a new array containing all but the first +n+ element of +self+,
- *  where +n+ is a non-negative Integer;
+ *  Returns a new array containing all but the first +count+ element of +self+,
+ *  where +count+ is a non-negative integer;
  *  does not modify +self+.
  *
  *  Examples:
@@ -8018,7 +8033,7 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
 
 /*
  *  call-seq:
- *    array.dig(index, *identifiers) -> object
+ *    dig(index, *identifiers) -> object
  *
  *  Finds and returns the object in nested object
  *  specified by +index+ and +identifiers+;
@@ -8294,21 +8309,21 @@ rb_ary_deconstruct(VALUE ary)
  *
  *  You can create an \Array object explicitly with:
  *
- *  - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
+ *  - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
  *
  *      [1, 'one', :one, [2, 'two', :two]]
  *
- *  - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
+ *  - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
  *
  *      %w[foo bar baz] # => ["foo", "bar", "baz"]
  *      %w[1 % *]       # => ["1", "%", "*"]
  *
- *  - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
+ *  - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
  *
  *      %i[foo bar baz] # => [:foo, :bar, :baz]
  *      %i[1 % *]       # => [:"1", :%, :*]
  *
- *  - \Method Kernel#Array:
+ *  - Method Kernel#Array:
  *
  *      Array(["a", "b"])             # => ["a", "b"]
  *      Array(1..5)                   # => [1, 2, 3, 4, 5]
@@ -8317,7 +8332,7 @@ rb_ary_deconstruct(VALUE ary)
  *      Array(1)                      # => [1]
  *      Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
  *
- *  - \Method Array.new:
+ *  - Method Array.new:
  *
  *      Array.new               # => []
  *      Array.new(3)            # => [nil, nil, nil]
@@ -8372,8 +8387,8 @@ rb_ary_deconstruct(VALUE ary)
  *
  *  == Example Usage
  *
- *  In addition to the methods it mixes in through the Enumerable module, the
- *  +Array+ class has proprietary methods for accessing, searching and otherwise
+ *  In addition to the methods it mixes in through the Enumerable module,
+ *  class \Array has proprietary methods for accessing, searching and otherwise
  *  manipulating arrays.
  *
  *  Some of the more common ones are illustrated below.
@@ -8421,9 +8436,9 @@ rb_ary_deconstruct(VALUE ary)
  *
  *     arr.drop(3) #=> [4, 5, 6]
  *
- *  == Obtaining Information about an +Array+
+ *  == Obtaining Information about an \Array
  *
- *  Arrays keep track of their own length at all times.  To query an array
+ *  An array keeps track of its own length at all times.  To query an array
  *  about the number of elements it contains, use #length, #count or #size.
  *
  *    browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
@@ -8438,7 +8453,7 @@ rb_ary_deconstruct(VALUE ary)
  *
  *    browsers.include?('Konqueror') #=> false
  *
- *  == Adding Items to Arrays
+ *  == Adding Items to an \Array
  *
  *  Items can be added to the end of an array by using either #push or #<<
  *
@@ -8459,7 +8474,7 @@ rb_ary_deconstruct(VALUE ary)
  *     arr.insert(3, 'orange', 'pear', 'grapefruit')
  *     #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
  *
- *  == Removing Items from an +Array+
+ *  == Removing Items from an \Array
  *
  *  The method #pop removes the last element in an array and returns it:
  *
@@ -8499,11 +8514,11 @@ rb_ary_deconstruct(VALUE ary)
  *     arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
  *     arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
  *
- *  == Iterating over Arrays
+ *  == Iterating over an \Array
  *
- *  Like all classes that include the Enumerable module, +Array+ has an each
+ *  Like all classes that include the Enumerable module, class \Array has an each
  *  method, which defines what elements should be iterated over and how.  In
- *  case of Array's #each, all elements in the +Array+ instance are yielded to
+ *  case of Array#each, all elements in +self+ are yielded to
  *  the supplied block in sequence.
  *
  *  Note that this operation leaves the array unchanged.
@@ -8530,7 +8545,7 @@ rb_ary_deconstruct(VALUE ary)
  *     arr                   #=> [1, 4, 9, 16, 25]
  *
  *
- *  == Selecting Items from an +Array+
+ *  == Selecting Items from an \Array
  *
  *  Elements can be selected from an array according to criteria defined in a
  *  block.  The selection can happen in a destructive or a non-destructive
@@ -8563,13 +8578,13 @@ rb_ary_deconstruct(VALUE ary)
  *
  *  == What's Here
  *
- *  First, what's elsewhere. \Class +Array+:
+ *  First, what's elsewhere. Class \Array:
  *
  *  - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
  *  - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
  *    which provides dozens of additional methods.
  *
- *  Here, class +Array+ provides methods that are useful for:
+ *  Here, class \Array provides methods that are useful for:
  *
  *  - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
  *  - {Querying}[rdoc-ref:Array@Methods+for+Querying]
@@ -8582,7 +8597,7 @@ rb_ary_deconstruct(VALUE ary)
  *  - {Converting}[rdoc-ref:Array@Methods+for+Converting]
  *  - {And more....}[rdoc-ref:Array@Other+Methods]
  *
- *  === Methods for Creating an +Array+
+ *  === Methods for Creating an \Array
  *
  *  - ::[]: Returns a new array populated with given objects.
  *  - ::new: Returns a new array.