Как стать автором
Обновить

Комментарии 30

ff сказал "out of memory" и продолжил жить
У меня linux dev версия висела около 3х минут, пока я её не убил.
нечто похожее: 44-я версия на linux, немного зависла, уже собирался убить, но firefox восстановил работу.
Это от железа может зависеть?
У меня 46.0a2. Возможно он убивает когда память заканчиваться начинает.
Подтверждаю, перед тем как выдать out of memory, FF съел дополнительный гигабайт памяти (ровно гигабайт).
при отладке обнаружилось что коллекция всё еще инициализировалась как массив
Если бы сериализовался объект, то в нём не было бы тысяч null'ов. Проверка типов помогла бы увидеть проблему на раннем этапе.
а, понял. при изменении надо было бы внести правки в правила сериализации?
Не в правила сериализации (которых в js нет), а в инициализацию объекта.
Изначально автор работал с массивом, но потом решил превратить его в объект. А вот инициализацию исправить забыл. Поскольку ключи у него были числовые, js никак не ругался, когда в массив куда-нибудь в индекс 100500 писалось значение, хотя предыдущих индексов в нём нет. Js оптимизирует такие "дырявые" массивы и не создаёт пустые недостающие промежуточные индексы, просто устанавливает свойство length. А вот при сериализации все дыры закрываются и в итоговой строке получаются миллионы null'ов и на последнем месте единица. Вернее, должны получаться, потому что браузер в процессе виснет и до финала не доходит.
При использовании нечисловых индексов JS и не заругается, т.к. массив тоже объект. Просто JSON.stringify выдаст пустой массив.
Когда я сменил логику с books.push(book) на books[getId()] = book надо было еще и books = [] поменять на books = {}, но я этого не сделал, а JS за типами не следит, и при том что id цифровой воспринял это как номер ячейки.

Ну и соотвественно на JSON.stringify вывел все null перед ячейкой 2e+6*random. Точнее попытался...
А ведь если подумать, это уязвимость. Вроде как у гуглов и т.п. за такое денежку платят =)
Ну это весьма косвенная уязвимость, в том плане что и Array.apply(null, Array(0x7fffffff)) тоже можно такой считать, но в нормальной ситуации внешние данные не должны влиять на индексы массива. Ну и сериализация всегда опасное дело, которое требует повышенной внимательности.
Сэкономлю время таким же любопытным:

Array.apply(null, Array(0x7fffffff))
Uncaught RangeError: Invalid array length
На значения по скромнее он не ругается, но да эффект конечно не такой мощный как с индексом.
Косвенная, возможно, только вот первое, что мне пришло в голову — https://jsfiddle.net/MrGobus/fj5xut89/, в гугле делает страницу безответной хотя отдаем должное, закрыть вкладку возможно, в файрфоксе либо смотрим ролик, либо умираем, кстати слушая звук, до момента, когда система предложит снять задачу. Несложно догадаться, что кое кому, кто любит рассказывать о том, как он чего то добился вложив 100500 денег в контору «Рога и Копыта», это может показаться удачной идеей для фокусировки внимания целевой аудитории на контенте с целью увеличения клиентской базы =) и он применит это в интернет рекламе. И вот, вместо того, чтобы смотреть пирацкий «Карточный домик» или «Наруту» многие будут слушать трели о том, как быстро разбогатеть в полной беспомощности перед такой вот «косенной» уязвимостью=)
Хмм, действительно интересная идея, правда сделать вкладку не закрываемой под linux-chome я так и не смог.
Я зарепортил на хромиум. Надеюсь они поняли что я имею ввиду. (:
Зачем так длинно писать, если JSON.stringify(Array(0x7fffffff)) должен дать тот же эффект (или Array(2e9))?
JSON.stringify(Array(0x7fffffff)) писать в коде никто не будет, а у автора реальный пример из жизни. Но сократить можно, конечно.
Причем здесь нестрогая типизация?
Это неверная инициализации переменной — сугубо Ваша ошибка изза усталости или неопытности, уж сами решайте.
Например в строготипизированных языках, в которых есть указатели, можно их сложить вместо их значений, что будет в результате — сами понимаете. Но это не проблема языка, компилятор или интепритатор не должен следить за тем, что Вы пишите, он выдаст ошибку только если он не может это выполнить.

Ударив себя молотком по пальцу — не вини молоток
а подвесить скорее всего и так можно

var x = [];
x[0x7fffffff]=0;
console.log(x);
проверил, нода висит
Что логично, так как 'console.log(x)' это по сути 'JSON.stringify' с форматирование, обратной связью для формирования отступов и записью в stdout.

Просто зависаний от 'console.log''а ждут многие, а от сериализации нет.
Правда это скорее психология. Во всяком случае большинство знакомых программистов этому удивились.
Нет, тут дело в том, что элементарно проитерировать массив с 2e9 элементов, даже в том c++ займет время, без вывода куда либо
Строгая типизация уменьшает риск человеческого фактора. И если говорить про молотки, то я бы сравнил строгую типизацию с толстой перчаткой, вроде бы и палец не всегда убережёт, и мешает иногда, но на стройке без перчаток не очень...

П.С.: Я за опциональную типизацию в JS.

Ну а что до указателей, то я как человек учивший в 12 лет первым серьёзным языком С++, без интернета и по учебнику C#, много их наелся постигая дзен.
Для уменьшения фаторов риска, используют соответствующие инструменты, JSHint например и здоровый крепкий сон. И как я вижу Вы пренебрегли всем этим и пытаетесь переложить ответственность на интерпретатор и типизация тут не при чем.
Про сон вы правы, увы и сейчас занимаюсь тем же. Не зря же сон идет первыми двумя пунктами рекомендаций (;
А вот jslint не обнаружил это, хотя я бы скорее удивился обратному.
Должен, поэтому и создаются языки типа Rust. Говорить "ахах, сам виноват" глупо, когда этой ошибки можно было избежать проверкой типов. Строгая типизация не панацея, есть и другие техники компилятора, но её было бы достаточно, чтобы вывести ошибку на этап компиляции.
> зависание происходит на уровне нативного кода функции JSON.stringify

Если это действительно так, то никто из браузеров событийку пока не осилил. =(
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории