- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
let array = [-2, 4, -10, 8];
let count = 0;
for (let i = 0; i < array.length; i++) {
if (!String(array[i]).startsWith("-")) {
count += array[i]
}
}
console.log(count) // 12
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+1
let array = [-2, 4, -10, 8];
let count = 0;
for (let i = 0; i < array.length; i++) {
if (!String(array[i]).startsWith("-")) {
count += array[i]
}
}
console.log(count) // 12
Пробовался в speed'кодинге, получил задачу: "написать код для нахождения суммы всех положительных элементов массива", ну и наскоро получилось такое xD
И вот именно поэтому начинать программировать нужно с «Си».
50% багов и уязвимостей в мире, имхо, от сишных сериализаций и парсеров. Остальные в PHP.
От strcpy(), memcpy() и printf() ещё. Хлебать говно с выходом за границы сишных массивов мы будем ещё очень долго.
А надо было пилить свой говнопарсер и годами отлавливать в нём баги, страдать при добавлении новых полей и изучать что там записалось в хекс-редакторе? Только тогда сишники примут в свою касту?
разумеется, речь идет о тех данных, которые не нужно валидировать (там нет указателей), и которые не будут меняться.
З.Ы. Ну и чтобы не было иерархии и желательно вообще коллекций, само собой. Ну и строк переменной длины чтобы не было. Тогда вообще прям идеальный кейс.
зачем валидировать инты?
>править руками,
огромное количество конфигов нереально руками исправить, сейчас даже дырки в файрволе тулой открывают.
алсо, у некоторых конфигов вообще есть только гуй
>читать глазами,
огромное количество конфигов нереально галазми читать, сейчас даже настройки сервисов через тулу читают
алсо, у некоторых конфигов вообще есть только гуй
>поддерживать
что?
>обновлять
что не так?
>передавать на другие машины...
тут-то что не так, если у меня структура упакована верно?
Ты бы поглядел сколько времени у жавоёба уходит на серилазиацию в джсон и обратно рефлексией, и понял бы, как пиздато сишнику с указателем на структуру в памяти)
Ну ты какой-то вырожденный случай рассматриваешь, когда у тебя фиксированная структура из трёх сраных интов и вообще насрать на их значения...
Не хочу спорить короче, наебался я уже с сишными структурами. Как своими так и унаследованными. Не нравится жсон - возьми более подходящий готовый сериализатор.
Конечно же дерево строк разной длинны так хранить не нужно, но очень часто структуры бывают именно статические, а разве у тебя в железе таких структур нет?
И вот в сишке у меня есть такая возможность -- взять память, и натянуть на структуру, а в высокоуровневом говне -- нет.
Файлы нужны для динамичных вещей, которые будут меняться, которые потом обновлять и поддерживать придётся...
Первый байт это размер кукорямбы (беззнаковое целое)
Второй байт состоит из восьми флагов: тилли, вилли, билли итд.
Остальные два это целое беззнаковое (это всё за пределы x86 не выходит, так что байт ордер ты знаешь)
Как ты вот такое распарсишь?
Практика показывает, что через год-другой эта железка будет возвращать какой-нибудь массив температур в Яунде, первый байт окажется variable-length интом, а при включенном флаге тилли там ещё пять байт прилетает...
Поэтому стримо-вьюхой, которая безопасно читает по одному полю с указанным типом и эндианом.
Если и мапать -- то только в приватную структуру, чтобы не дай бог остальной код эту срамоту не видел и на её поля не завязался.
Сильно ли поменялась структура MBR за последние тридцать семь лет?
Если у тебя поменяется структура, то у тебя обосрется любая десериализация, будь то сгенерированный по схеме код или даже JSON (хотя последний переживет конечно добавление новых полей)
Суть в том, что многие бинарные форматы имеют какие-то штуки с переменной длиной (массивы, иногда даже полиморфные), оффсетами (относительно какого-нибудь хедера в середине) или особенным кодированием (variable-length числа, к примеру).
Какие-то куски этих форматов можно замапать на сишные структуры. Но далеко не все. При этом надо не забывать о проверках на вылет за буфер.
Посмотри на gpt (массив с указанным в заголовке шагом) или usb дескрипторы (полиморфный массив), я молчу о файлухах.
> Сильно ли поменялась структура MBR за последние тридцать семь лет?
Я не историк, но на английской вики аж 6 каких-то вариантов, LBA тоже поди сбоку прикручено.
З.Ы. Ага, в 96 году. Ну 24 года из 37 ничего не менялось.
>проверках на вылет за буфер.
Это тоже актуально только для переменной длины.
Если такой длины нет, то я просто определяю размер статически, и теку
>24
ну ок, ну вот)
Ну вот у тебя там в начале структуры какая-то длина. Её проверить надо, видимо. Вдруг там написано 4, а реально пришло 3 байта? Это вполне штатная ситуация, когда со всяким говном работаешь.
На подобное штуке обосрался openssl и словил heartbleed.
Если поменялся формат (Petuh, Petuh2 итд) то конечно нужно передавать sizeof()
А если они нарушили протокол, но пускай сами нахуй идут, не?
Хотя конечно с другой стороны я не хочу прочитать неинициализированную память, и получить UB или незамапаленную память, и получуть фолт (особенно если я драйвер например, и могу уронить систему)
Тут ты прав
Откуда я знаю? Так вышло. Deal with it.
> упасть
Упасть -- это лучший исход, имхо. Хуже когда какие-нибудь данные закорраптятся или утекут. Или вообще RCE.
MAKAKA: смотрите! В си можно сохранить на диск два байта, считать их, и обойтсь без сериализации
Всё: ну конечно, хакер пошлет тебе по сети неверное значение, ты выделишь неверного размера буфер, и хакер сделает тебе RCE
- лаба
> хакер пошлет тебе по сети неверное значение
- суровая реальность
Да-да-да, вот именно так одним тёмным вечером думал простой программист Джон, создавая очередную дырень, которая через N лет приведёт к потере охулиарда долларов у незадачливых пользователей.
> Хотя конечно с другой стороны я не хочу прочитать неинициализированную память, и получить UB или незамапаленную память, и получуть фолт (особенно если я драйвер например, и могу уронить систему)
Oh, sweet summer child! Если бы всё ограничивалось простым сегфолтом — мы бы жили в прекрасном мире розовых единорогов.
Помнишь «Heartbleed»? Почитай описание, если не помнишь, и впечатлись.
Если вы боитесь дырени, то вам и джейсон с жабкой нахуй не нужен, а уж про все эти undefined в JS я вообще молчу
херблядь тут вообще не причем: пришедшие по сети данные логично проверять, если не ты их послал. Я же не о том
пришедшие данные логично проверять
fxd
Отмазка прям в стиле microsoft: а вы нормальным клиентом ходите, тогда наш сервак падать не будет.
Если я пишу хайлоад приложение, работающее с бигдатой, то у меня одни требования
А если веб сайт для себя то другие.
Если я пишу библиотеку для криптографии, которая будет работать с данными, которые хуй знает кто подготовил, то у меня одни требования.
А если я хочу сейф своей игры сделать, или тулу, которая читает задокументированную статическую структуру, то другие
не?
Ага, а потом люди качают специально сформированный сейв и остаются без биткоинов. Именно поэтому у меня и нет доверия к софту. Вообще.
Почитай про Starcraft EUD. Тебе понравится ;)
я всё равно не понимаю как можно что-то переполнить считав байт с флагами
З.Ы. Иди читай, блин, там чуваки целую экосистему вокруг этого бага в старкрафте развернули.
что мешает мне насрать неверный int в json?
ладно, почитаю потом
P. S. Ещё как-то натыкался на любопытную статью, в которой описывалось создание полноценного ботнета из игроков небезызвестного «Counter Strike». Причём, если мне память не изменяет, там для вступления в коллектив достаточно было вообще просто внутри игры посмотреть информацию о таком весёлом сервере. Очень хороший пример того, как на сишке легко и просто сериализовывать данные, да.
> расскажи опжлста как ты спиздишь биткоины с помощью специально сформированного сейфа, если его структура статична
«Heartbleed», там тоже хендшейк статичен.
если он не берет ни код, ни имена внешних тулов из структуры, то как он что считает?
если размер буфера известен заранее, то самое ужасное, что может случиться, это буфер заполнится мусором
Например, я буду ждать там 0 или 1, а получу 23
Тоже самое может случиться и в JSON, это тоже придется валидировать
Да, придётся. Но, по крайней мере, сам парсер уже более-менее отвалидирован без тебя.
В том и проблема, что большая часть сишного кода -- это ебучие самодельные парсеры! Строк, блобов, пакетов, чёрта лысого. Думаешь от хорошей жизни сейчас кругом ASLR и прочие DEP?
Ну они отвечают только за то, что поля внутри структуры будуть читаться с правильным оффсетом. А вот что она замапана как надо и куда надо и прочитана полностью и без мусора отвечаешь ты и только ты.
Вот именно. А нормальный, вменяемый парсер должен уметь правильно валидировать поступающие ему на вход данные по-хорошему ещё на стадии парсинга — и уж точно до того, как отдать их клиентскому коду.
Ну вот появилось у тебя требование: считать байт со значением не меньше единицы и не больше сотни. В самописном сишкопарсере тебе придётся делать ёбанный костыль — и таким образом ты пойдёшь по пути создания ёбанного говнопарсера с дырами, о чём я написал выше. Унылый жаваёб просто напишет что-нибудь вроде @validate(GREATER, 0, LOWER, 101) или что они там для такого пишут — и пойдёт дальше писать фабрики стратегий.
Короче говоря, любое дело нужно делать правильно с самого начала, иначе в конце ты рискуешь получить дырявое говно.
А что еще он должен?
Я вот люблю SOAP, и считаю, что вменяемый парсер должен поддерживать схемы и ENUM.
а JSON не поддерживает из коробки, и потому он говно, не?
Фишка в том, что всё это не бесплатно.
JSON в миллион раз более не бесплатен, и самое главное -- он совершенно бесполезен, когда тебе нужно считать заранее задокументированную структуру НЕ в JSON формате
Быть удобным, расширяемым и безопасным инструментом. Сишный «парсер», увы, подходит только по первому пункту, и то исключительно тогда, когда тебе надо считать два инта и три флага.
структура mbr, как было замечено выше, не менялась 24 года. Зачем тут что-то расширять?
И зачем мне расширять что-то, если и писун и читун данных лежат в одном модуле трансляции?
>безопасным
что такое "безопасность" для случая с интами и флагами статичной структуры, и как json бы решил эту проблему?
>>> Хотя конечно с другой стороны я не хочу прочитать неинициализированную память, и получить UB или незамапаленную память, и получуть фолт
На что я тебе резонно заметил, что чтение неинициализированной памяти может привести к гигантским баграм и миллионам мух слитых паролей.
это что угодно из того, что может в принципе сделать программа.
Ох, не хочется мне разбивать твои розовые очки…
https://landave.io/2018/05/7-zip-from-uninitialized-memory-to-remote-code-execution/
>>> The initialization of some member data structures of the RAR decoder classes relies on the RAR handler to configure the decoder correctly before decoding something. Unfortunately, the RAR handler fails to sanitize its input data and passes the incorrect configuration into the decoder, causing usage of uninitialized memory.
Да, всё верно: ты извлекаешь обычный, безобидный архив, после чего на твоём компьютере выполняется произвольный код. Ну как, тебе ещё не страшно жить?
А если бы он читал JSON, то конфигурация всегда была бы корректной?
Например выполнить шеллкод, который превратит твою программу в готсе.
Ну вот я записал в свою структуру Petuh с байтами и флагами какое-то говно, у меня получились всратые флаги и всратые байты, и где тут шелл код такой, что он не работал бы будь там json?
я не доебываюсь, я правда пытаюсь понять
не понял: в структуре будет указатель на функцию что ли?
Не обязательно прям в этой. Возможно в какой-то другой, на которую можно повлиять или сослаться мусором из этой.
Если же адрес функции мы вычисляем на основе данных, то данные нужно валидировать даже если они пришли через JSON.
Грубо говоря если в структуре есть поле "смещение в таблице функций", то нельзя в такое поле писать случайное число, даже если это JSON
помню, в двух местах надо было исправлять
> Если вы боитесь дырени, то вам и джейсон с жабкой нахуй не нужен, а уж про все эти undefined в JS я вообще молчу
Джейсоны я могу более-менее безопасно сериализовывать/десериализовывать без адского геморроя и паранойи. Более того, во многих случаях я могу себе позволить даже не проверять всякие там размеры буфера, потому что в этом случае да, всё, чем мне будет грозить выход за границу — это IndexError и 500 клиенту, ну или через что там мы общаемся. А выход за границу массива в сишке мне грозит таким ворохом проблем, что даже как-то неудобно объяснять.
на JSON ты не переполнишь буфер, а вот undefined ты получишь отлично.
Ну да, а можно вообще взять либу для парсинга джейсонов и потечь.
> на JSON ты не переполнишь буфер, а вот undefined ты получишь отлично.
Как я получу undefined, если у меня в языке undefined нет?
в джаве ты точно так же ловно получишь null, например.
> для парсинга джейсонов и потечь.
Если мне нужно читать json или хранить иерархические данные неизвестного размера то да, разумеется
Да блядь, как можно сравнивать undefined и undefined behavior?!
Разве что там действительно сложная структура, а в файле насрано, но мы не о сложных структурах.
Ну, к примеру, файл оказался короче заранее известного размера. А ты это забыл проверить. Или длинее. Упс.
В памяти я выделил место, например массив
И конечно инициализировал его нулями (я же не еблан иметь неинициализированную память)
Если файл короче, то в части полей меня ждут ноли.
совсем как в json, не?
>длинее
обычно я сообщаю размер приемника тому, кто читает. Это же сишка.
Помнишь, ты вчера спрашивал, что делать, если архитектура в голову не помещается?
Так вот сишнику помимо этой архитектуры и заката солнца вручную приходится держать в голове ещё кучу правил: вот это занулить, вот это передать, вот тут не забыть сравнить...
Я не спорю с тем, что сишник все делает вручную, если у него не плюсы конечно
Я говорил сектантам, что если запоминать каждую мелочь, которая "ну мелочь же, как её не запомнить хорошему программисту", то места на бизнес-логику не останется. Но сектанты будут продолжать закатывать Солнце вручную только потому, что в современной книжке 1960 года написали, что программирование на статушне безгцёвой работает быстрее лишпа и позволяет разрабатывать программы быстрее, чем отлаживать перфокарты дыроколом и липкой лентой.
Но нет, сектанты не будут использовать выразительный язык потому, что деды не использовали гц и динамушню.
Но у дедов не было света, а у тебя, %username%, я почти уверен, в сортире, откуда ты читаешь мой пост с телефона-с-которого-можно-не-только-звонить, которого у дедов не было, сейчас горит лампочка, и ты её при выходе не отключишь ибо не хочешь светодиоды часто нагревать/охлаждать. Так выкрути лампочку и ходи в туалет гордо как ходили деды!
И вот таким образом простое и элегантное решение превращается в ёбанное нагромождение костылей, в котором критические баги 10/10 находятся трижды в день.
Именно поэтому хвалить простоту сериализации данных на сишке может только обманутый, неразобравшийся человек.
Или когда эта структура поностью принадлежит тебе.
Хакеры тебе не шлют по сети никакие данные.
Или когда структура заранее задокументирована (см пример с MBR)
>обманутый, неразобравшийся человек.
ну давайте напишем такое на JS или Java и сравним с си
https://govnokod.xyz/_27177/#comment-589971
обращаю внимание: данные там взяты из спецификации, их не по сети пользователь послал
> взяты из спецификации
И что это меняет?
Не, я согласен что есть случаи когда похуй... Но, к примеру, как много "программистов" ожидает, что рандомный сайт может стукнуться к их хуйне, запущенной на локалхосте (да, недоступной извне)?
Наш разговор начался с того, что сишка такие задачи умеет решать легко, а Java нет.
getU8(), getU16LE(), getSubView() и т.п.
ты бы заполнял вручную, через getU8(), читая под капотом примитивы побайтово?
А какую проблему бы ты этим решил?
В данном простейшем случае никакую, разве что про размеры и вылеты за них вообще думать не придётся.
Но мне ведь после MBR'а наверное захочется файлуху попарсить или что-то ещё интересное? А вот там этот view-stream уже на всю катушку работает.
ну слава богу
>размеры и вылеты за них вообще думать не придётся.
а как можно куда-то вылетить с обычной структурой?
>наверное захочется файлуху попарсить
ну да, а потом SMB или NFS. Но почему мы всё время придумываем задачу, решение для которой не подходит?
Разумеется, чтение рендомных данных нужно валидировать
Потому что MBR или твоя структурка из 4 байт -- это вырожденные случаи, которые на практике довольно редко встречаются?
Возьми тот же GPT. Казалось бы, там тоже массив структурок. Но ты не можешь его выразить сишным массивом т.к. интервал не известен. Надо оффсеты считать и кастовать каждую по-отдельности. И тут уже очень легко вылететь и читнуть что-то не то.
А если я сам пишу и "клиент" (который прочитает) и "сервер" (который запишет) то я могу взять структуру?
>интервал не известен
Тогда структура данных не статична, ее размер заранее неизвестен, и мое решение не подходит, я не спорю
Да бери, мы тут вроде как не твои начальники, и даже пользоваться твоими клиентами не собираемся.
Только будь готов к тому, что через полгода тебе станет совершенно необходимо высрать в эту структуру путь к файлу или там URL. И тогда перед тобой будут два стула: либо выкинуть всё, что ты написал, и переписать на нормальный парсер, либо начать пилить собственный велосипед, внося в наш мир ещё немножко софта с критическими дырами.
во-первых совершенно не очевидно, почему так (см пример с mbr)
во-вторых что мешает добавить поле в .h файл, и все перекомпилировать?
"сервер" начнет писать новые данные, "клиент" их читать.
Если же мне нужно будет сичтать старые данные, то я сосну, да
Потому что это программирование, чувак. Меняющиеся каждую неделю требования (и неважно, рабочие или просто твои) — это суровая реальность жизни. Я глубоко удивлён, что кому-то это требуется объяснять.
> во-вторых что мешает добавить поле в .h файл, и все перекомпилировать?
Ну да, как-то так думали программисты из «Майкрофоста», когда делали MAX_PATH. Сколько там десятков лет это дерьмо фиксят и всё пофиксить не могут?
>это суровая реальность жизни
снова отсылаю к примеру MBR.
>MAX_PATH
MAX_PATH уже пофиксили недавно (ограничение можно снять), но на него завязался охулион пользователей, так что это не попадает под определение "клиент и сервер пишу я"
Ну да, в Windows 10 1607. А сколько там этот MAX_PATH не менялся? Лет двадцать-тридцать? Понимаешь, к чему я веду?
Можешь гарантировать, что завтра не придумают MBRv2 с «Косынкой» и анимешными девочками, который тебе тоже окажется нужным поддерживать?
Потому что это была константа в .h файле, с которым скомпилировались клиенты
Это не мой случай
>Можешь гарантировать, что завтра не придумают MBRv2
Если его придумают, то отвалится охулион готового кода, так что он будет обратно совместим
> он будет
«Это меня не коснётся, я точно уверен».
--Завтра тебе понадобится проехать 500 километров, и твой велосипед соснет
--Но работа не будет на таком расстоянии
--«Это меня не коснётся, я точно уверен».
А мне стали рассказывать, что если завтра я захочу в эту структуру добавить поле сломав совместимость, то старые данные я не смогу десериализовать.
Теперь еще рассказывают, что Pydantic в питоне умеет валидировать данные, а сишка нет.
— «Это меня не коснётся, я точно уверен».
Либо
Я живу там, где захочу (сам пишу клиент и сервер) зимы тут нет
Если ты готов поставить на это часы своей жизни, проведённые за разгребанием своего же говна — ну, что поделать.
> сам пишу клиент и сервер
А у тебя требования никогда не меняются?
Я пока не понял, о каких часах речь.
>А у тебя требования никогда не меняются?
Если они поменяются, то я добавлю поле, и перекомпилирую программу.
Если никто за пределами меня не пользуется моей серизализацией, то я не вижу проблем
Завтра тебе понадобилось насрать в свою структуру путь к файлу. Твои действия?
Однако и у JSON есть такие проблемы: если завтра мне придется насрать в него мегабайтный BMP, то наверное не логично использовать текстовый формат (мне придется делать base64/uuc же, да?): это может занять лишнее место, особенно если мне надо гонять много таких структур и часто
Я лучше тогда переключусь на бинарный формат, чей парсер будет хранить размер данных, и всё валидировать.
Так что любой формат имеет свои плюсы и минусы
> так что придется переключиться на другой подход
Я ответил на твой вопрос?
> иначе мне придется выделять MAX_PATH, и валидировать, что она кончается нулём
И стать одним из миллионов несчастных, чьи программы нельзя устанавливать слишком глубоко в ФС, ага. Сам же писал о том, что в «Microsoft» это дерьмо похоронили.
> мегабайтный BMP
Тут надо проводить отдельное исследование, что приходиться сериализовывать чаще: строки произвольной длины или мегабайтные БМПмы? Эмпирически мне вот кажется, что первое. Но да, если тебе надо гонять очень много и очень часто — инструмент придётся менять.
Но и экономить на спичках тоже смысла мало. В перекатном петухе, например, капчи гоняются в виде картинок по «JSON», никто не умер, удобно, все довольны.
Не совсем.
Более мощные подходы обычно тратят больше ресурсов. Например, Oracle развернуть сложнее, чем сохранить csv, но Oracle бесконечно мощнее.
По сути, ты предлагаешь всегда использовать Oracle, потому что если вдруг мне придется выбирать из миллиона записей по сложной функции, то csv не подойдет.
>И стать одним из миллионов несчастных
Верно, потому я и сказал, что строки неизвестной длины хранить в моем подходе не нужно.
>что приходиться сериализовывать чаще: строки произвольной длины или мегабайтные БМПмы?
Согласен. потому и было сказано, что каждый подход имеет и плюсы, и минусы.
Дерево строк неизвестной длины в миллион раз проще сохранить в JSON, например>
>капчи гоняются в виде картинок по «JSON»
Хочется думать, что каптча не занимает мегабайт.
Для любого подхода можно найти пример, когда он не подходит (либо когда является оверхедом): и для json, и для "сишной сериализации"
Хороший пример, кстати. В Швеции по стандарту запятая — десятичный разделитель, и поэтому csv тут немного сломан. Сколько человековеков было потрачено на поиски косяков в огромных дампах данных в этом говноформате.
Хоть в JSON, хоть в csv, хоть где
Нет, я предлагаю не использовать нерасширяемый и опасный способ сериализации данных.
> Для любого подхода можно найти пример, когда он не подходит (либо когда является оверхедом): и для json, и для "сишной сериализации"
Главная проблема твоей «безопасной» (структура фиксированной длины без всяких там коллекций/иерархий, you name it) «сишной сериализации» в том, что она до крайности хуёво расширяется. Надо добавить коллекцию? Надо добавить строку? Появилось две версии структуры, включающиеся в зависимости от значения флагов (здравствуй, iphdr)? Ты выкидываешь весь свой код и пишешь всё заново.
Более того, «сишная сериализация» не имеет никаких возможностей для валидации данных, что создаёт широчайший простор для «забыли проверить».
Этих причин достаточно для того, чтобы считать «сишную сериалилизацию» антипаттерном. Любые другие антипаттерны обладают похожими свойствами: прямо сейчас они выглядят удобно и быстро, но в перспективе порождают только опасные баги и хуёво поддерживаемый код.
CSV точно так же не расширяемый и не безопасный (вон, Снаут пример привел), однако вряд-ли все хотят заменить его на СУБД
>до крайности хуёво расширяется.
Как и любой бинарный формат в общем-то.
COM тоже не расширяется, а создается новый интфейс.
Можно ли считать COM антипаттерном?
Ну а где он используется-то, помимо задач «быстренько выгрузить говно и прогнать через run-once скриптик»? Сейчас вроде как везде либо «JSON», либо «SQLite».
> Как и любой бинарный формат в общем-то.
Из-за позднего часа ты неправильно десериализовал слово «расширяется».
Если мне нужно добавить строковое поле в «protobuf» — я открою свой .proto и добавлю туда одну строку. Если мне нужно добавить его в «pydantic» — я открой свой Petuh.py и добавлю туда одну строку. Если мне нужно добавить его в «сишную сериализацию» — я выкидываю нахуй весь код и переходу на «protobuf» или ещё какую-нибудь хуйню. Именно поэтому «сишная срализация» и хуёво расширяется.
В огромном количестве бизнес и интерперйс питушни
> я открою свой .proto и добавлю туда одну строку.
А что будет с клиентом предыдущей версии? Или там передается схема?
В COM вот не передается. Значит ли это, что COM использовать не нужно?
>я выкидываю нахуй весь код
или просто добавляешь структуру в файл, и перекомпилируешь клиент и сервер
В чат заходит MITM.
Блядь, не смешно. Я на одной и той же сишной структуре три раза граблями по ебалу получал, добавляя в неё новые биты...
А структура то простейшая, битовые флаги да немного интов, как в примере гостя. Ничто не предвещало беды.
З.Ы. Парсилась она именно по-сишному.
Предполагалось, что обратная совместимость там не нужна.
то есть условие "клиент и сервер перекомпилируются вместе" не выполняется
>обратная совместимость
действительно, обратную совместимость получить в JSON намного проще
Не, она там реально не нужна. Но с жсоном я бы ошибку об отсутствующем поле быстрее получил. И быстрее бы разобрался что вообще происходит. А с сишкой просто нули и иногда нерабочая опция.
Это просто пример, чем заканчиваются "но я же внимательный", "здесь точно не нужна совместимость, они же вместе собираются, зачем мне поле с версией" и "забьём паддингом до 512 чтобы не париться с длинами".
Три раза одни и те же грабли с интервалом в пару лет, да.
а с WSDL схемой и прокси классом ты бы даже не скомпилировался, но если я предложу заменить JSON на SOAP/WSDL, то никто меня не поддержит, правда?
Ну wdsl и json тут перебор, имхо. А какой-нибудь протобуф норм зашёл бы. Тоже ведь схема какая-никакая.
>перебор
>имхо
> какой-нибудь
видишь, существуют разные варианты, и ты между ними выбираешь. Это входит в противоречие с утверждением, что "json всегда лучше "
Клиент и сервер - это разные программы, а значит гарантированно их разные версии могут запускаться вместе.
Под такую питушню должен быть номер версии как одно из полей данных. Как минимум, для того, чтобы вывести "запустите меня с сервером моей версии" и упасть. Чтобы ни у программиста, ни у пользователя не возникало ни питушни, ни вопросов, откуда питушня.
Обычно для доморощенных питушень цикл жизни программы такой:
1. активная разработка (меняется формат, надо для тестов иметь одну версию),
2. длительное использование (формат не меняется, запуск питузов прописан по крону или по мануалу пользователя, программист забывает, что он написал),
3. правка бага/фичи (новые требования, часто незначительные, а иногда значительные изменения протокола),
4. goto 2
Хм, ну я вроде нормально парировал твой выпад с MBR при помощи GPT. Они из одной области, очень большая вероятность, что тебе придётся поддерживать оба.
Тебе нужны лексер и парсер для кода и клиент JSON для сохранения конфигов, нет разве?
Могу ли я использовать json для конфигов (чтобы поддержать новую версию) и сериализацию структуры для IPC между двумя своими процессами, запускаемыми из одной версии программы?
Или я должен тратить циклы CPU на json всегда?
Я тебе уже говорил, что не являюсь ни твоим начальником, ни твоим клиентом. Что хочешь — то и делай.
> и сериализацию структуры для IPC между двумя своими процессами, запускаемыми из одной версии программы
Я бы посоветовал использовать уже написанные библиотеки для IPC, потому что сам их писать заебёшься ещё до того, как напишешь собственный протокол синхронизации.
> Или я должен тратить циклы CPU на json всегда?
Тебе bormand уже приводил реальный пример того, как не тратить циклы на JSON, но всё равно иметь бульмень безопасную десериализацию.
Вопрос "могу ли я" означает "считаешь ли ты допустимым"
>Я бы посоветовал использовать уже написанные библиотеки для IPC
>протокол синхронизации.
Особенно это актуально для пересылки двух байт
> как не тратить циклы на JSON, но всё равно иметь бульмень безопасную десериализацию.
генерацией парсера?
Это хорошее решение, но оно более громоздкое, и я бы хотел понять, чем оно лучше.
Вы в который раз используете термин "безопасную", но я к сожалению так и не понял, чем небезопасного в статической структуре с байтами
Я не твой исповедник, чтобы тебе указывать, что допустимо, а что нет.
> Особенно это актуально для пересылки двух байт
О, мсье никогда не писал своего IPC? Рекомендую, очень увлекательное занятие.
> но я к сожалению так и не понял, чем небезопасного в статической структуре с байтами
Отсутствие гарантированной валидации.
>считаешь ли ты допустимым
хорошим ответом явлчется
>Я не твой исповедник,
?
ладно, попробуем по другому: как бы сделал ты?
>О, мсье никогда не писал своего IPC?
мсье пересылал данные между двумя программами, довольно простые, тем самым способом, и не столкнулся ни с какими проблемами, кстати (вряд-ли это можно назвать полноценным IPC)
>Отсутствие гарантированной валидации.
JSON так же не имеет валидации. Ее имеет pydantic и всякие другие либы, к сериализации отношения не имеющие
В четыре часа ночи? Разумеется.
> как бы сделал ты?
Один мудуль программы читает конфиги в «JSON», другой мудуль программы использует либу для IPC и пересылает структуры без ебли.
> тем самым способом
Каким? Сокеты, пайпы, шаренная память, мейлслоты, COM?
> к сериализации отношения не имеющие
Десериализация — это весь процесс от «вот у нас какие-то байты» до «это валидный объект Petuh». Поэтому разумеется, имеющие.
Это такое "иди в дупу, не хочу отвечать"?P)
>Один мудуль программы
>другой мудуль программы
То есть использование двух подходов тут нас не пугает, но если один из них заменить на сишную сериализацию, то сразу станет пугать?
>Каким?
Named pipes, но по идее разницы быть не должно, если я не шлю их по сети.
>Десериализация — это весь процесс о
> «это валидный объект Petuh».
В таком случае десериализации нету из коробки ни в python (без пайдантик) ни в Java, ни даже в JavaScript, ведь не существует способа гарантировать, что в поле IQ у петуха мы не запишем "-1" или NaN
ps: а вообще ты прав про четыре часа, надо собираться
Да. Потому что ты проводишь некорректное сравнение. Корректным было бы парсинг одной половины конфига JSON-ом, а другой половины — сишной сериализацией YAMLем.
> Named pipes
А, ну так там всё сделано за тебя — и соединения, и синхронизация, и даже кое-какую сериализацию и ту запилили (см. «PIPE_READMODE_MESSAGE»). Веселье-то начинается когда тебе надо организовать IPC в расшаренной памяти.
> из коробки
А кто про искаропки-то что-то говорил? Никто не говорил, странное какое-то требование, ненужное.
Спокойного утра, guest6.
У меня есть два модуля
Один использует подход Foo, другой Bar.
И это нормально.
но если Foo вдруг становится равным сишной сериализации, то сравнение становится некорректным
>А, ну так там всё сделано за тебя
Я говорил о сериализации, а она нужна при серийной передаче данных.
В шаред мемори наверное можно ничего не сериализовать (если все ее клиенты скомпилированы вместе на одном языке), но нужно пирдолица с синхронизацией доступа к памяти
> Никто не говорил, странное какое-то требование, ненужное.
Наличие чего-то из карбоки -- большой плюс для маленьких несложных программ, особенно в си, где нет совсем простых средств для установки зависимостией
Спокойного утра, гост
Кстати, вполне популярная практика. Как минимум в osu и factorio такое видел. Байтоёбский хедер, а потом gzip + json/csv.
Отличная мысль. Противники сишной высериализации слишком сильно поднатужились в её обсирании, что получившейся волной брызг смыло всё.
Очевидно, они говорят или хотели сказать, или должны были сказать о какой-то другой валидации.
Скажем, о валидации коллекции другой формы ([1,2] vs [1, {"2": 3}]) или об упрощении написания инструментов валидации (жсон шхема) в силу малой фантазии насчёт форм жсон-коллекций.
Но питушня про число от 0 до 100 и прочие высказывания о валидации питушень внутри жсон, преподнесённые как аргументы в пользу жсон, требуют дальнейшего пояснения. Лично я не могу сказать, чем условие 0 <= x && x <= 100 в коде для x из жсона отличается от условия 0 <= x && x <= 100 в коде для x из бинарушни, если нет упомянутых жавовских аннотаций.
______________
* я сказал "чуть менее, чем всех" просто на всякий случай вроде микроконтроллеров и подобной питушни. Для всего остального можно написать статически питуизированную инфрапитушню (с расширением для Object aka void*, чтобы вместить себя банку сгужсонки), которая за счёт крестошаблонов и компиляции только нужного, либо за счёт оптимизации на этапе компиляции и/или за счёт работы жида доведёт производительность до уровня рукописной сиштушни за авторством Царя.
Это не аргументы в пользу «ЖСОН», это аргументы против бездумного каста структуры в набор байт и обратно.
При всём уважении к адептам структурированной питушни, которые ссут на сишную реализацию бинарной высериализации,
что в этом плохого?
Про MBR и GPT мы говорим в 2020, когда обе этих питушни уже существуют, и мы можем выбирать привычные инструменты 2020. Сейчас это смузихлёбный JSON, который им подходит.
Но давайте представим, что мы в 1983. До GPT ещё где-то одно десятилетие, до JSON - где-то пара десятилетий.
Зададимся вопросом, что нам использовать для работы с GPT, чтобы
* эта питушня не тормозила сейчас - в 1983,
* эта питушня поддерживала формат, который мы не знаем, но будет сделан через десятилетие,
* эта питушня была не менее удобной, чем формат, который мы не знаем, но будет сделан через два десятилетия,
* эту питушню не обосрали на неизвестном нам сайте несуществующей ближайшее десятилетие страны через четыре десятилетия?
Так и сейчас, если выбирать формат, надо рассматривать потребности настоящего и грубые мазки насчёт будущего (ну хотя бы версию вписать в поля, и всё). Совершенно не факт, что наша программа проживёт более 10 лет. Скорее наоборот, виндушня с 256 символами на путь - это исключение из правил, о котором мы знаем из-за ошибки выжившего. Как легендарная советская электроника, которую мы, херы, миллениалы и зумеры, знаем больше по тем экземплярам из остатков, но не видим полной картины.
То, что это создаёт неконсистентность. Программа работает с двумя одинаковыми по своей сути объектами совершенно разными способами. Более того, при необходимости распарсить ещё какую-нибудь подобную питушню программисту придётся решать дополнительную задачу: какой способ выбрать? А будет ли простой каст структуры безопасным? А не понадобится ли его расширять? А может, парсер будет оверкиллом? Может, писать велосипед будет быстрее?
Если же подобная бинарушня парсится сразу хорошим, годным, расширяемым способом (спросите bormand как!), то и вопросов не возникает: надо ещё что-то распарсить — просто сделаем парсер по примеру уже существующих.
Каст структуры в бинарушню и обратно подобен goto, только без goto. На малых «дистанциях» и в очень специфических случаях (goto error; struct {int, int}) он облегчает жизнь, как только случай становится чуть более общим — всё, нам приходится либо переписывать всё с нуля, либо мириться с лапшой (goto) или RCE (каст). Именно это и называется «антипаттерном».
При естественном ходе событий неконсистентность зародится сама из-за течения времени. Будет новый код про GPT и старый про MBR. Можно будет решить, переписывать ли код про MBR с учётом новых реалий, или и так сойдёт (старый код хороший, либо он какой есть, но MBR отомрёт).
Для нового формата скорее всего будут использовать новый способ парсинга как для GPT, либо придумают ещё более новый третий, который родился за эти десятилетия, либо если способ парсинга MBR и так хорош, будут использовать его.
Пусть похожие питушни парсятся разным способом, но главное - чтобы парсились хорошо
> случай становится чуть более общим — всё, нам приходится либо переписывать всё с нуля, либо мириться с лапшой
И нет ничего такого, чтобы в один момент взять и выкинуть к хренам старый парсер и переписать на новый формат. Если изначально были слабые знания о требованиях и сильные незнания об изменениях, переписать всё к хренам - нормально.
А лапшу можно пытаться инкапсулировать, если она инкапсулируется. Скажем, если к бинарной питушне добавилась в конце жсонщина (как рар в раржпеге).
Не понимаю, к чему ты начал обсуждать форматы, ну да ладно. В 1983-м году бинарушня была суровой необходимостью, потому что иначе было никак. В 2020-м году использовать бинарушню с целью экономии тактов или байт — это в 99% случаях признак говна в голове. Конечно, есть ещё всякие микроконтроллеры, но тут нужно призвать дядю defecate-plusplus, чтобы он наглядно продемонстрировал, что экономия на спичках даже в среде микроконтроллерщиков приводит к неврозам.[/color]
> эту питушню не обосрали на неизвестном нам сайте несуществующей ближайшее десятилетие страны через четыре десятилетия?
В этом треде никто не обсирал ни «MBR», ни «GPT». Обсирались лишь подходы к их парсингу.
если писать мморпг сервер и клиент к нему, то бинарный протокол (протобуф или что-то аналогичное с версионностью и валидацией, а не просто memcpy) может быть обоснован
также странно будет гонять жсон в манямирке модбаса, где в целом смотрят с непониманием на пакеты длиннее 255 блять
Ну да, я же и написал про экономию байтов. Всяческий хуйлоад под это не попадает, там не экономия, там просто необходимость — иначе всё либо вообще не заработает, либо заработает, но крайне хуёво.
> манямирке модбаса, где в целом смотрят с непониманием на пакеты длиннее 255 блять
Какой багор )))
Прямо вспоминаю, как пару лет назад писал сериализатор бинарушни в 150 текстовых символов, среди которых ещё и несколько запрещённых было. Где-то на ГК даже алгоритм описывал. Наебался тогда надолго, ещё и совсем недавно там баг нашли, пришлось фиксить, лол.
Часто нельзя себе позволить купить время программистов, которые напишут весь нужный код одновременно. Всегда будет эволюция и состояние, когда есть код из настоящего, прошлого, далёкого прошлого и архаичных времён. Может, в каком-то проекте поддерживают разработки А. Лавлейс.
Борманд же показал пример MITM в играх, где игра была и "клиентом" (когда писала файл), и "сервером" (когда читала файл) одновременно, но пришёл MITM в роли писаря файлов и зашкварил "сервер", подсунув в файле какое-то говно с "запросом" (сохранением игори).
Для сетевых сервера и клиента с протоколом справедлив классический MITM. Если они на одной забуренной во внутреннюю сеть машине, то это ещё ладно, хотя и тут Борманд показал: произвольный сайт может зашкварить твой внутренний HTTP и HTTPS сайт пользуясь твоим браузером. Думая дальше в этом направлении, можно представить торрент-клиент, скайп и подобные программы, которые можно попытаться заставить обратиться к локальному серверу, если порты подходят.
Да потому что «сишный парсер» хорошо подходит только для сферических задач в вакууме, когда у тебя нет ни сложной структуры, ни коллекций переменной длины (строки!), вообще ничего нет, кроме тупых интов. И ладно бы только это, так у тебя и валидации вообще никакой не должно быть, потому что как только ты начинаешь делать валидацию — ты вступаешь на Путь Говна, Ебли и Геморроя. И вся обещанная простота превращается в CVE.
то есть все задачи без переменной длины и иерархии мы считаем сферическими?
>как только ты начинаешь делать валидацию — ты вступаешь на Путь Говна, Ебли и Геморроя.
Про какую валидацию речь?
Я не сказал "каст к указателю на структ всегда лучше json" (жаль, если так прочиталось), я сказал, что есть задачи, которые легко решаются, а в джаве (и вообще языках без прямого доступа к неуправляемой памяти) они не решаются.
И любой валидации.
> Про какую валидацию речь?
Любую. Вот как только среди всех возможных байтовых представлений твоей структуры появляется невалидное — «сишный парсер» становится непригоден.
невалдным можем быть число 32 в поле foo, разве json может мне как-то гарантировать, что его там не будет?
Тебе это будет гарантировать парсер, на вход которому ты подашь схему с валидацией. Буквально на днях же я тут приводил реальный пример «Pydentic»:
Всё, твоя программа безопасна. Потребуется завтра проверять, что имя начинается с прописной буквы? Ты в этом же месте напишешь простой и ясный проверяющий код. Другой человек захочет сделать проверку — ему будет крайне просто разобраться, как нужно (а ведь на месте другого человека можешь оказаться ты).
А что с сишным парсером? Правильно, тебе придётся хуй знает где хуй знает как пилить хуй знает что. Может, это будет кусок парсера, может, надо будет звать is_valid() после парсинга, может, звать отдельные функции для каждого поля… Как я и сказал — геморрой.
* делаю структуру
* делаю в ней метод age_must_be_positive
что такое validator, кстати? Это разве часть JSON?
На сишке?
> что такое validator, кстати? Это разве часть JSON?
Это часть «Pydentic».
ну метод может быть только в сишке-с-классами, на сишке придется делать функциб validate для всей структуры видимо.
Это вопрос к удобству сишки, а не к парсингу
>Это часть «Pydentic».
Тогда причем же тут json?
Декларативная валидация это круто (В джанге есть тоже например), но мы сравнивали способы десерилазиации
Кто её будет вызывать? Когда этот кто-то её будет вызывать? Как сигнализировать об ошибке?
> Тогда причем же тут json?
Притом, что он тут обеспечивает безопасную «первичную» десериализацию данных.
А валидация, как ни странно, является частью десериализации объекта.
Да JSON то тут причем? Вызывать её будет питоновская либа, точно так же она могла бы вызывать ее после десериализации бинарных данных
>обеспечивает безопасную «первичную» десериализацию данных.
Что такое "безопасная первичная десериализация"?
Что такого можно записать в uint8_t, что будет небезопасно, но будет безопасно при записи в обычный int в питоне?
Вот именно, причём тут JSON? Мы обсуждаем способы десериализации объектов, а не только JSON.
> Вызывать её будет питоновская либа
Ну то есть непонятно кто и непонятно когда. А может и вообще никто, если забыли и/или не разобрались.
> Что такое "безопасная первичная десериализация"?
Это когда я могу написать «json.loads(some_shit)» и быть более-менее уверенным, что не сделал дыру с RCE.
> Что такого можно записать в uint8_t, что будет небезопасно
Размер последующей строки.
Честно говоря, я о такой возможности даже не думал, хотя и осознанно включал CSRF-питушню для внутреннего сайта.
Но такой частный случай CSRF я не рассматривал. Это же можно сделать удалённое администрирование питухов с серым IP на основе "CSRF-прокси"!
А паддинги всякие? Они же по идее любую структуру и любой массив могут зашкварить, из-за чего идея с высериализацией в сишке работает только для строк в формате ASCII, а никакие структуры высериализовывать нельзя?
Специально вместо того, чтобы компилятор пошевелил мозгами на малом числе нестандартных платформ, сишник должен в каждой программе попердолиться на этот счёт, не ошибиться, чтобы доказать своё звание сишника.
P.S. Ну если пирфоманс важен, сделали бы user defined питушню вместо UB. Если 99% моих пользователей - большие индейцы, выставляю флаг племени больших индейцев. Если наоборот - выставляю флаг маленьких. То же с представлением чисел и прочим.
а если у студента в лабе была фраза "нажмите любую клавишу" то он жал кнопку питания ноутбука
З.Ы. Любой приличный редактор такое переживает. Да и браузеры тоже, по крайней мере фф.
Хотя, "press any key" обычно пишут в конце программы, так что ладно.
Хотя на некоторых ноутах она именно как клавиша оформлена... Видимо такой и попался.
https://ideone.com/5Ytc9r
Что-то не прокатило ;(
Я ещё хотел ~(0x80000000 & *begin), но не прокатило по, вероятно, той же причине. И даже если скастить оба операнда & в unsigned int, не прокатило.
P.S. А вот если реинтерпретировать питушню в скобках как unsigned и потом сдвинуть, должно сработать.
Кратенько для пока ещё психически здоровых людей: берём бесконечный список, откусываем от него X элементов (для X из [-2, 4, -10, 8]), конкатенируем получившиеся списки, считаем длину итогового списка, которая будет искомой суммой. В качестве кобенации операций map и concat выбран оператор (=<<), который для монады "список" имеет именно такую реализацию.
Перепиши на J. Там поди в 3-4 символа уложишься.
Проверь.
Но где-то на ГК, кажется, писали, что либо в новой сишке, либо в новых крестах решили закрепить дополнительного питуза, поскольку другие не нужны. А может быть, не было такого.
> Хотя всё равно интересно, разрешено ли знаковому биту лежать где попало, а не в старшем бите.
Имеется в виду отношение стандартов C или C++ разных версий к данному вопросу.
Джаваскрипт, гори в огне,
Джаваскрипт, тони в говне
Передача говна из Java в JS в JCEF в моем случае позволена только через строки.
Приходится писать
матапушто
дебилы, блядь
(bool)"false"
Дебилы, блядь.
Дебилы, блядь.
Дебилы, блядь.
Cannot convert value of type 'String' to type 'Bool' in coercion
Дебилы, блядь.
Вот от "PHP" не ожидал, если честно. До последнего думал, что правильно сконвертит.
Ну да, кто ж знал, что на языке для анимации кнопочек начнут писать серьёзные проекты и даже сервера?
Вроде же arguments.caller выпилили ради оптимизации хвостушни.
Не, на MDN пишут, что по соображениям безопасности 22 года(!) назад выпилили. Чтобы код из странички в привилегированную гуйню и экстененшены не лез, скорее всего. И вообще оно работало только в IE и никогда не было частью стандарта.
Тем более на практике она особо и не критична.
Ну и проблема заинлайнивания, жидования и состэковывания была и раньше. Сколько-то лет писали, что использование в коде try ... catch приводит к сливу пирфоманса, что функция с такими матными словами мешает жиду V8 работать в полную силу. А тут надо перейти от заинлайнивания на N уровней к заинлайниванию на "бесконечность" уровней.
А это невозможно. Тут либо ты тратишь память и сохраняешь контекст либо нет. Разве что для чистых функций можно заново проиграть весь вызов для отладчика.
* возможность с помощью new получить объект, а не примитивушню (ради которой наверно в движках прописывают поведение для этих всех new PrimitivePituz)
* автокаст объекта к булу (null - false, не null - true)
Кстати, для новой питушни возможность помещения значения в зашкваренную коробку сразу пофиксили:
Хм, т.е. я должен явно заявлять, что функция -- не конструктор?
P.S. Вообще, надо сделать как в хаскеле. Тогда для питушни с большой буквы будет эффект с new, а для питушни с маленькой - эффект без new.
Да, в жс бы перегрузку операторов и метатаблицы.
spelling disk is used for magnetic storage (e.g. hard disks) while disc is used for optical storage (e.g. compact discs, better known as CDs
> английский езе
- руске вдмо тозе
https://en.wikipedia.org/wiki/Spelling_of_disc
нам, как не нейтив спикерам, можно писать discette и не париться