А теперь о Ruby и Redmine
Я таки нашел, в чем причина вот этого бага:
no method error [] for class nil
https://bugs.launchpad.net/ubuntu/+source/ruby1.8/+bug/949011
Вкратце: недавно в большинстве реализаций хэш таблиц была найдена имманентная уязвимость к потенциальным DDOS атакам на веб-приложения, связанная с тем что атакующий мог посылать запросы такого вида, что внутри приложения они приводили к обращению к хэш-таблице всегда к одному bucket. Т.е. передавать ключи, которые после обработки hash-функцией всегда давали одно и то же значение, убивая эту таблицу из O(1) в O(N) и съедая тем самым процессор.
В руби это дело исправили:
https://launchpad.net/ubuntu/+source/ruby1.8/1.8.7.249-2ubuntu0.1
http://launchpadlibrarian.net/94639065/ruby1.8_1.8.7.249-2_1.8.7.249-2ubuntu0.1.diff.gz
конкретно эти строки:
++extern unsigned long rb_genrand_int32(void);
++
++void
++Init_st(void)
++{
++ hash_seed = rb_genrand_int32();
++}
+- register int key = 0;
++ register unsigned long key = hash_seed;
Формально, в норме бы ничего не поменялось, после этого.
НО: в редмайне оказалось место, где работа зависит от порядка элементов в хэше:
/usr/share/redmine/app/models/setting.rb,166
setting ||= new(:name => name, :value => @@available_settings[name]['default'])
тут происходит примерно такое: создается новый объект Setting и ему устанавливаются атрибуты name и value. И, это ключевой момент, установка атрибута value ЗАВИСИТ от наличия уже установленного атрибута name:
т.е. оно использует name чтобы получить значение по умолчанию из @@available_settings и далее пытается из него получить значение атрибута 'serialized'
Раньше это работало, а после секьюрити-фикса - работает в зависимости от rb_genrand_int32.
Так что ошибка, вообще говоря, в редмайне. Надеятся на порядок в хэш-таблице, это бред.
PS: а вот и фикс, месяц назад: http://www.redmine.org/projects/redmine/repository/revisions/8909/diff/trunk/app/models/setting.rb
no method error [] for class nil
https://bugs.launchpad.net/ubuntu/+source/ruby1.8/+bug/949011
Вкратце: недавно в большинстве реализаций хэш таблиц была найдена имманентная уязвимость к потенциальным DDOS атакам на веб-приложения, связанная с тем что атакующий мог посылать запросы такого вида, что внутри приложения они приводили к обращению к хэш-таблице всегда к одному bucket. Т.е. передавать ключи, которые после обработки hash-функцией всегда давали одно и то же значение, убивая эту таблицу из O(1) в O(N) и съедая тем самым процессор.
В руби это дело исправили:
https://launchpad.net/ubuntu/+source/ruby1.8/1.8.7.249-2ubuntu0.1
http://launchpadlibrarian.net/94639065/ruby1.8_1.8.7.249-2_1.8.7.249-2ubuntu0.1.diff.gz
конкретно эти строки:
++extern unsigned long rb_genrand_int32(void);
++
++void
++Init_st(void)
++{
++ hash_seed = rb_genrand_int32();
++}
+- register int key = 0;
++ register unsigned long key = hash_seed;
Формально, в норме бы ничего не поменялось, после этого.
НО: в редмайне оказалось место, где работа зависит от порядка элементов в хэше:
/usr/share/redmine/app/models/setting.rb,166
setting ||= new(:name => name, :value => @@available_settings[name]['default'])
тут происходит примерно такое: создается новый объект Setting и ему устанавливаются атрибуты name и value. И, это ключевой момент, установка атрибута value ЗАВИСИТ от наличия уже установленного атрибута name:
  def value=(v)
    v = v.to_yaml if v && @@available_settings[name]['serialized']
    write_attribute(:value, v.to_s)
  endт.е. оно использует name чтобы получить значение по умолчанию из @@available_settings и далее пытается из него получить значение атрибута 'serialized'
Раньше это работало, а после секьюрити-фикса - работает в зависимости от rb_genrand_int32.
Так что ошибка, вообще говоря, в редмайне. Надеятся на порядок в хэш-таблице, это бред.
PS: а вот и фикс, месяц назад: http://www.redmine.org/projects/redmine/repository/revisions/8909/diff/trunk/app/models/setting.rb
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)




no subject
private
# Returns the Setting instance for the setting named name
# (record found in database or new record with default value)
def self.find_or_default(name)
name = name.to_s
raise "There's no setting named #{name}" unless @@available_settings.has_key?(name)
setting = find_by_name(name)
unless setting
setting = new(:name => name)
setting.value = @@available_settings[name]['default']
end
setting
end
end
(no subject)
no subject
и эти люди запрещают мне ковырять в носу.
(no subject)
(Anonymous) - 2012-03-26 14:53 (UTC) - Expandno subject
no subject
(no subject)
(no subject)
(no subject)
(no subject)
no subject
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
Неоднократно сталкивался с тем, что в рубёвых гемах начинают валиться тесты при переходе с руби 1.8 на руби 1.9 только по той причине, что код основывается на порядке элементов в хэше. Кучу примеров видел и фиксил.
В 1.9 хэши стали сохранять порядок, в котором добавляются элементы. Такое изменение логично, потому что с теорией знакомы не все (пичаль-пичаль), а руби старается следовать принципу least surprise.
➜ ~ rvm use ruby-1.9.3-p125 && ruby -e "h = {}; h[:b]=2; h[:a]=1; p h" Using /home/dnnx/.rvm/gems/ruby-1.9.3-p125 {:b=>2, :a=>1} ➜ ~ rvm use ree-1.8.7-head && ruby -e "h = {}; h[:b]=2; h[:a]=1; p h" Using /home/dnnx/.rvm/gems/ree-1.8.7-head {:a=>1, :b=>2}(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(Anonymous) - 2012-03-26 11:03 (UTC) - Expand(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
no subject
Когда-то, помню, я довольно преуспел в создании хеш-функций и оптимизации всяких хешевых структур.
(no subject)
(no subject)
(no subject)
no subject
(no subject)
(no subject)
(no subject)
(no subject)
no subject
(no subject)
no subject
Метнем фекалий.