Project

General

Profile

case_equality_sequence_predicates-check_argc_before_deref.patch

Check argc before dereferencing argv. - 0x0dea (D.E. Akers), 06/19/2015 10:13 PM

View differences:

ChangeLog
1
Fri Jun 19 16:10:22 2015  D.E. Akers  <0x0dea@gmail.com>
2

  
3
	* enum.c: add case equality arity to sequence predicates.
4

  
5
	* test/ruby/test_enum.rb: add tests for above.
6

  
1 7
Fri Jun 19 14:53:35 2015  Nobuyoshi Nakada  <nobu@ruby-lang.org>
2 8
	* proc.c (rb_mod_define_method): now requires a block direct to
enum.c
1043 1043
    return ary;
1044 1044
}
1045
#define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
1045
#define ENUMFUNC(name, argc) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
1046 1046
#define DEFINE_ENUMFUNCS(name) \
1047 1047
static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
......
1061 1061
} \
1062 1062
\
1063 1063
static VALUE \
1064
name##_eqq(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1065
{ \
1066
    return enum_##name##_func(rb_funcall(MEMO_CAST(memo)->v2, id_eqq, 1, i), MEMO_CAST(memo)); \
1067
} \
1068
\
1069
static VALUE \
1064 1070
enum_##name##_func(VALUE result, struct MEMO *memo)
1065 1071
DEFINE_ENUMFUNCS(all)
......
1075 1081
/*
1076 1082
 *  call-seq:
1077 1083
 *     enum.all? [{ |obj| block } ]   -> true or false
1084
 *     enum.all?(pattern)             -> true or false
1078 1085
 *
1079 1086
 *  Passes each element of the collection to the given block. The method
1080 1087
 *  returns <code>true</code> if the block never returns
......
1083 1090
 *  cause #all? to return +true+ when none of the collection members are
1084 1091
 *  +false+ or +nil+.
1085 1092
 *
1093
 *  If instead a pattern is supplied, the method returns whether
1094
 *  <code>pattern === element</code> for every element of <i>enum</i>.
1095
 *
1086 1096
 *     %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
1087 1097
 *     %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
1098
 *     %w[ant bear cat].all?(/t/)                        #=> false
1099
 *     [1, 2i, 3.14].all?(Numeric)                       #=> true
1088 1100
 *     [nil, true, 99].all?                              #=> false
1089 1101
 *
1090 1102
 */
1091 1103
static VALUE
1092
enum_all(VALUE obj)
1104
enum_all(int argc, VALUE *argv, VALUE obj)
1093 1105
{
1094
    struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
1095
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
1106
    struct MEMO *memo = MEMO_NEW(Qtrue, argc ? *argv : 0, 0);
1107
    rb_check_arity(argc, 0, 1);
1108
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all, argc), (VALUE)memo);
1096 1109
    return memo->v1;
1097 1110
}
......
1109 1122
/*
1110 1123
 *  call-seq:
1111 1124
 *     enum.any? [{ |obj| block }]   -> true or false
1125
 *     enum.any?(pattern)            -> true or false
1112 1126
 *
1113 1127
 *  Passes each element of the collection to the given block. The method
1114 1128
 *  returns <code>true</code> if the block ever returns a value other
......
1117 1131
 *  will cause #any? to return +true+ if at least one of the collection
1118 1132
 *  members is not +false+ or +nil+.
1119 1133
 *
1134
 *  If instead a pattern is supplied, the method returns whether
1135
 *  <code>pattern === element</code> for any element of <i>enum</i>.
1136
 *
1120 1137
 *     %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
1121 1138
 *     %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
1139
 *     %w[ant bear cat].any?(/d/)                        #=> false
1122 1140
 *     [nil, true, 99].any?                              #=> true
1141
 *     [nil, true, 99].any?(Float)                       #=> false
1123 1142
 *
1124 1143
 */
1125 1144
static VALUE
1126
enum_any(VALUE obj)
1145
enum_any(int argc, VALUE *argv, VALUE obj)
1127 1146
{
1128
    struct MEMO *memo = MEMO_NEW(Qfalse, 0, 0);
1129
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
1147
    struct MEMO *memo = MEMO_NEW(Qfalse, argc ? *argv : 0, 0);
1148
    rb_check_arity(argc, 0, 1);
1149
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any, argc), (VALUE)memo);
1130 1150
    return memo->v1;
1131 1151
}
......
1352 1372
/*
1353 1373
 *  call-seq:
1354 1374
 *     enum.one? [{ |obj| block }]   -> true or false
1375
 *     enum.one?(pattern)            -> true or false
1355 1376
 *
1356 1377
 *  Passes each element of the collection to the given block. The method
1357 1378
 *  returns <code>true</code> if the block returns <code>true</code>
......
1359 1380
 *  <code>true</code> only if exactly one of the collection members is
1360 1381
 *  true.
1361 1382
 *
1383
 *  If instead a pattern is supplied, the method returns whether
1384
 *  <code>pattern === element</code> for exactly one element of <i>enum</i>.
1385
 *
1362 1386
 *     %w{ant bear cat}.one? { |word| word.length == 4 }  #=> true
1363 1387
 *     %w{ant bear cat}.one? { |word| word.length > 4 }   #=> false
1364 1388
 *     %w{ant bear cat}.one? { |word| word.length < 4 }   #=> false
1389
 *     %w{ant bear cat}.one?(/t/)                         #=> false
1365 1390
 *     [ nil, true, 99 ].one?                             #=> false
1366 1391
 *     [ nil, true, false ].one?                          #=> true
1392
 *     [ nil, true, 99 ].one?(Fixnum)                     #=> true
1367 1393
 *
1368 1394
 */
1369 1395
static VALUE
1370
enum_one(VALUE obj)
1396
enum_one(int argc, VALUE *argv, VALUE obj)
1371 1397
{
1372
    struct MEMO *memo = MEMO_NEW(Qundef, 0, 0);
1398
    struct MEMO *memo = MEMO_NEW(Qundef, argc ? *argv : 0, 0);
1373 1399
    VALUE result;
1374
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
1400
    rb_check_arity(argc, 0, 1);
1401
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one, argc), (VALUE)memo);
1375 1402
    result = memo->v1;
1376 1403
    if (result == Qundef) return Qfalse;
1377 1404
    return result;
......
1390 1417
/*
1391 1418
 *  call-seq:
1392 1419
 *     enum.none? [{ |obj| block }]   -> true or false
1420
 *     enum.none?(pattern)            -> true or false
1393 1421
 *
1394 1422
 *  Passes each element of the collection to the given block. The method
1395 1423
 *  returns <code>true</code> if the block never returns <code>true</code>
1396 1424
 *  for all elements. If the block is not given, <code>none?</code> will return
1397 1425
 *  <code>true</code> only if none of the collection members is true.
1398 1426
 *
1427
 *  If instead a pattern is supplied, the method returns whether
1428
 *  <code>pattern === element</code> for none of the elements of <i>enum</i>.
1429
 *
1399 1430
 *     %w{ant bear cat}.none? { |word| word.length == 5 } #=> true
1400 1431
 *     %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
1432
 *     %w{ant bear cat}.none?(/d/)                        #=> true
1401 1433
 *     [].none?                                           #=> true
1402 1434
 *     [nil].none?                                        #=> true
1403 1435
 *     [nil, false].none?                                 #=> true
1436
 *     [nil, false].none?(NilClass)                       #=> false
1404 1437
 */
1405 1438
static VALUE
1406
enum_none(VALUE obj)
1439
enum_none(int argc, VALUE *argv, VALUE obj)
1407 1440
{
1408
    struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
1409
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
1441
    struct MEMO *memo = MEMO_NEW(Qtrue, argc ? *argv : 0, 0);
1442
    rb_check_arity(argc, 0, 1);
1443
    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none, argc), (VALUE)memo);
1410 1444
    return memo->v1;
1411 1445
}
......
3501 3535
    rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
3502 3536
    rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
3503 3537
    rb_define_method(rb_mEnumerable, "first", enum_first, -1);
3504
    rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
3505
    rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
3506
    rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
3507
    rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
3538
    rb_define_method(rb_mEnumerable, "all?", enum_all, -1);
3539
    rb_define_method(rb_mEnumerable, "any?", enum_any, -1);
3540
    rb_define_method(rb_mEnumerable, "one?", enum_one, -1);
3541
    rb_define_method(rb_mEnumerable, "none?", enum_none, -1);
3508 3542
    rb_define_method(rb_mEnumerable, "min", enum_min, -1);
3509 3543
    rb_define_method(rb_mEnumerable, "max", enum_max, -1);
3510 3544
    rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
test/ruby/test_enum.rb
236 236
    assert_equal(false, @obj.all? {|x| x < 3 })
237 237
    assert_equal(true, @obj.all?)
238 238
    assert_equal(false, [true, true, false].all?)
239
    assert_equal(true, @obj.all?(Fixnum))
240
    assert_equal(false, @obj.all?(1..2))
239 241
  end
240 242
  def test_any
......
243 245
    assert_equal(false, @obj.any? {|x| x > 3 })
244 246
    assert_equal(true, @obj.any?)
245 247
    assert_equal(false, [false, false, false].any?)
248
    assert_equal(true, @obj.any?(1..2))
249
    assert_equal(false, @obj.any?(Float))
246 250
  end
247 251
  def test_one
248 252
    assert(@obj.one? {|x| x == 3 })
249 253
    assert(!(@obj.one? {|x| x == 1 }))
250 254
    assert(!(@obj.one? {|x| x == 4 }))
255
    assert(@obj.one?(3..4))
256
    assert(!(@obj.one?(1..2)))
257
    assert(!(@obj.one?(4..5)))
251 258
    assert(%w{ant bear cat}.one? {|word| word.length == 4})
252 259
    assert(!(%w{ant bear cat}.one? {|word| word.length > 4}))
253 260
    assert(!(%w{ant bear cat}.one? {|word| word.length < 4}))
261
    assert(%w{ant bear cat}.one?(/b/))
262
    assert(!(%w{ant bear cat}.one?(/t/)))
254 263
    assert(!([ nil, true, 99 ].one?))
255 264
    assert([ nil, true, false ].one?)
265
    assert([nil, true, 99].one?(NilClass))
256 266
  end
257 267
  def test_none
258 268
    assert(@obj.none? {|x| x == 4 })
259 269
    assert(!(@obj.none? {|x| x == 1 }))
260 270
    assert(!(@obj.none? {|x| x == 3 }))
271
    assert(@obj.none?(4..5))
272
    assert(!(@obj.none?(1..3)))
261 273
    assert(%w{ant bear cat}.none? {|word| word.length == 5})
262 274
    assert(!(%w{ant bear cat}.none? {|word| word.length >= 4}))
275
    assert(%w{ant bear cat}.none?(/d/))
276
    assert(!(%w{ant bear cat}.none?(/b/)))
263 277
    assert([].none?)
264 278
    assert([nil].none?)
265 279
    assert([nil,false].none?)
266
-