зеркало из https://github.com/github/ruby.git
Make any hash values fixable [Bug #17488]
As hnum is an unsigned st_index_t, the result of RSHIFT may not be in the fixable range. Co-authored-by: NeoCat <neocat@neocat.jp>
This commit is contained in:
Родитель
b2030d4dae
Коммит
20a8425aa0
11
hash.c
11
hash.c
|
@ -223,15 +223,10 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE))
|
||||||
default:
|
default:
|
||||||
hnum = other_func(a);
|
hnum = other_func(a);
|
||||||
}
|
}
|
||||||
#if SIZEOF_LONG < SIZEOF_ST_INDEX_T
|
if ((SIGNED_VALUE)hnum > 0)
|
||||||
if (hnum > 0)
|
hnum &= FIXNUM_MAX;
|
||||||
hnum &= (unsigned long)-1 >> 2;
|
|
||||||
else
|
else
|
||||||
hnum |= ~((unsigned long)-1 >> 2);
|
hnum |= FIXNUM_MIN;
|
||||||
#else
|
|
||||||
hnum <<= 1;
|
|
||||||
hnum = RSHIFT(hnum, 1);
|
|
||||||
#endif
|
|
||||||
return (long)hnum;
|
return (long)hnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1865,4 +1865,30 @@ class TestHash < Test::Unit::TestCase
|
||||||
{a: 1}.each(&->(k, v) {})
|
{a: 1}.each(&->(k, v) {})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_any_hash_fixable
|
||||||
|
20.times do
|
||||||
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
|
begin;
|
||||||
|
require "delegate"
|
||||||
|
typename = DelegateClass(String)
|
||||||
|
|
||||||
|
hash = {
|
||||||
|
"Int" => true,
|
||||||
|
"Float" => true,
|
||||||
|
"String" => true,
|
||||||
|
"Boolean" => true,
|
||||||
|
"WidgetFilter" => true,
|
||||||
|
"WidgetAggregation" => true,
|
||||||
|
"WidgetEdge" => true,
|
||||||
|
"WidgetSortOrder" => true,
|
||||||
|
"WidgetGrouping" => true,
|
||||||
|
}
|
||||||
|
|
||||||
|
hash.each_key do |key|
|
||||||
|
assert_send([hash, :key?, typename.new(key)])
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Загрузка…
Ссылка в новой задаче