Что такое безопасное программирование ?

Тема в разделе "WASM.ZEN", создана пользователем X-Shar, 17 фев 2018.

  1. X-Shar

    X-Shar Active Member

    Публикаций:
    0
    Регистрация:
    24 фев 2017
    Сообщения:
    354
    Вот интересно, здесь на форуме наверняка есть люди, которые слышали этот термин, а возможно даже являются специалистами в этой области ? :)

    Интересно ваше мнение, что по вашему мнению является "Безопасным программированием" ?

    Используете-ли вы какие-то стандарты, или готовые какие-то методики, если не секретная информация, то что конкретно используьете.

    Вот например, есть стандарт, "MISRA-C", очень ограничивает программиста, вплоть до расставления скобочек в коде и т.д.

    Как вы относитесь к таким стандартам ?

    Читаете-ли вы стандарты языка, нужно-ли знать компилятор, что-бы безопасно программировать ?

    В общем предлагаю пообсуждать это сдесь, кому интересно конечно. :)
     
  2. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    На мой взгляд, безопасное программирование - это:
    1. Использование заведомо проверенного кода. То есть, вы не берёте какой-то фреймворк и сразу внедряете его в проект, а детально понимаете, как та или иная функция работает вплоть до самого низкого уровня (системные вызовы, использование ресурсов и т.д.), то есть проводите серьёзное такое исследование и стресс-тестирование. OpenSource позволяет сделать это гораздо быстрее.
    2. Покрытие кода тестами.Гораздо проще протестировать какую-то функцию или какой-то класс и быть в нём на 95% уверенным, чем потом ловить странные баги при его использовании.
    3. Формирование определённых паттернов написания кода. Например, если вы пишете if() {}, то сразу же пишете и else {}, чтобы не забыть в будущем написать код для альтернативной ветки алгоритма. Или не использовать конструкции, которые могут приводить к UB вроде:
    Код (Text):
    1.  
    2. int i=5;
    3. i = ++i + ++i;
    4. printf("%d\n", i);
    5.  
    Иными словами, код дожен быть легко читаем и легко понимаем, а не быть результатом выпендрёжа какого-то конкретного человека с попыткой сказать "смотрите, как я могу!!!111".
    4. Тщательно контролировать доступ к памяти, проводить тесты под профилировщиками памяти типа valgrind с tool=memcheck.
    5. Обрабатывать ошибки на месте, а не ждать, что их обработает вызывающий код. Проверять, что занятый ресурс при обработке ошибок корректно освобождается. Этим правилом очень часто пренебрегают, так как писать правильный код по обработке ошибок долго, муторно и сложно. Да ещё сама функция из нескольких строк обрастает десятками дополнительных строк кода. Проблема ещё усугубляется тем, что функции освобождения ресурса тоже могут возвращать ошибки.
    6. Не "продавать динамическую память по дешёвке". Может, кто-то другой лучший термин придумает, но суть в том, что для вполне очевидных решений и алгоритмов выделяется чрезмерно много динамической памяти, в то время как реально для решения задачи может быть использовано гораздо меньшая её часть без какой-либо потери в производительности/качестве. А то можно ещё и бонус от кэша словить в случае уменьшения объёмов используемой памяти.
    7. Не допускать ни одного warning при компиляции кода. Любой waning должен быть исправлен.

    Это пока первое, что пришло на ум.
     
    X-Shar нравится это.
  3. X-Shar

    X-Shar Active Member

    Публикаций:
    0
    Регистрация:
    24 фев 2017
    Сообщения:
    354
    SadKo, благодарю за столь развернутый ответ. А эти выводы вы сделали из собственного опыта, или пользовались какими-то уже готовыми технологиями/стандартами ?

    Просто про то-что вы написали есть в стандартах, в частности про if ... else. Прикольно. :)

    И еще небольшей вопрос, что можно считать по вашему мнению динамической памятью ?

    Вот например, выделяю статичеки кусок памяти, например так:

    Код (Text):
    1. static char heap [MAX_HEAP]
    Далее делаю свой маллок, который будет выделять память в пределах heap, ну и free, который будет ее освобождать.

    Будет-ли это динамической памятью ?

    Кто-то говорит, что нет, т.к. мы используем уже выделенную кучу. А кто-то говорит, что да, т.к. мы выделяем и освобождаем память в процессе работы программы.

    Как вы считаете ?
     
  4. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Это опыт, особенно в части разгребания и переделывания чужого кода.

    Неудивительно. Люди не хотят повторно наступать на грабли.

    Любая память, для получения которой нужно выполнять больше операций, нежели чем простое сложение или вычитание.

    Это динамическая память с вашим кастомным аллокатором (распределителем памяти).
    Если бы вы при инициализации один раз выделили на хипе кусок памяти и разбили его на части под разные нужды, это не было бы динамической памятью. Например, так:
    Код (C):
    1.  
    2. u8_t *data = malloc(alot_of_data);
    3. if (data == NULL) // Сразу обрабатываем ошибки, да-да.
    4.   return ENOMEM;
    5.  
    6. u8_t *buf1 = data;
    7. data += some_chunk_size;
    8. u8_t *buf2 = data;
    9. data += some_another_chunk_size;
    10. ....
    11.  
    12. // Здесь код программы
    13.  
    14. // Выходим из программы
    15. free (data);
    16. data = NULL; // защищаемся от повторного free, если что.
    17.  
    Вот это конкретный канонический пример нединамической памяти. Вы выделили её один раз и дальше пользуете под свои нужды, пока программа либо модуль не завершится.

    Да, забыл ещё одно важное правило вписать:
    8. Обязательно обнуляйте указатели, которые были освобождены.


    Как вы считаете ?[/quote]
     
    X-Shar нравится это.
  5. im.

    im. Active Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    310
    X-Shar,
    Да, безусловно, интересная тема.
    Настоящее безопасное программирование в моем случае это набор инструментария, который защищен от случайной ошибки, я такой для себя написал на Си. Туда входят различные API для простейших задач, что-то strlcat, strlcpy, только я пошел дальше и расширил арсенал. Следующим шагом было соблюдение рекомендаций по размеру процедур, соблюдения целостности абстракции, это не менее важно. В целом я прихожу к выводу о том, что оценка безопасности кода упирается в возможности человеческого мышления, т.к. мы компилируем код в голове, моделируем возможные варианты исполнения, чтобы предвидеть проблемы, а это основа человеческого мышления - способность проектировать будущее опираясь на свой ранний опыт, т.е. строить будущее используя опыт прошлого (человеческая память). Поэтому борьба со сложностью признана основным императивом, мозг должен легко справляться.

    Технически в PE файл данный блок попадает как uninitialized область и не будет занимать лишнее место, до его загрузки в память.
    Загрузчик под это дело уже использует аллокатор виртуальной памяти и никакой разницы с VirtualAlloc здесь не будет, можно этот кусок кода поместить в отдельную секцию со своими аттрибутами.
     
    X-Shar нравится это.
  6. X-Shar

    X-Shar Active Member

    Публикаций:
    0
    Регистрация:
    24 фев 2017
    Сообщения:
    354
    В РФ тема достаточно новая, раньше софт делался "на коленках", сейчас на конец пришло понимание, что ошибка в софте может привести к еще большим последствиям, чем ошибка в том-же железе.

    Кстати, а каким-кто софтом пользуется для тестирования ?

    С точки зрения безопасности, тестирование занимает даже больше времени, чем разработка софта.

    Причем есть динамические тесты - это когда система рассматривается как "черный ящик".

    И статичекие, где тестируются прям каждая функция в коде, т.е. на функцию подаются значения, в том-числе и вызывающие ошибки. Далее смотрят как функция себя ведет, если ошибка, то должна вернуть правильный код ошибки и т.д.

    Вообще, если делать все по технологии, то сам процесс кодирования становится не такой-уж и интелектуальной работой.

    Ведь в начале система проектируется кем-то даже просто на бумаге, потом из этого проектируются уже конкретные алгоритмы и реализация нужных функций.

    Программисту в данном случае уже попадает готовая реализация (алгоритм), которую нужно просто перевести в код.

    В США по похожей схеме уже давно работают, поэтому программист, он-же наверное обидное слоово "кодировщик" считается самая низкоквалифицированная работа, поэтому они набирают индусов и т.д., по сути крайне рутинная работа. :)
     
  7. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Как тогда узнать, что написал говнокод, который пытается два раза один и тот же блок деаллочить? :)
    Надо писать не безопасный код, а максимально опасный, чтоб при малейшей ошибке систему в бсод ронял. Так и кодить нормально люди начнут учиться :)
     
  8. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.546
    Адрес:
    Russia
    Перенес из хипа. Чтоб тема приобрела серьезность в обсуждении. А то щас налетят имеющие свое мнение.
     
  9. im.

    im. Active Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    310
    X-Shar,
    Да. По большей части разумно. По поводу индусов, тут есть прикол. Формально это может и так, но процесс разработки ПО это задача недетерминированная, поэтому проектированием занимаются программисты де-факто и работа эта невидимая. Те кто этого не осознают и набирают индусов в конечном итоге получают массу проблем и код их фуфло, тратят дополнительные ресурсы на тех самых тестировщиков и гоняют циклы рефакторинга до бесконечности.
    Если бы изгачально можно было спроектировать решение задачи на 100% и кодинг был бы рутиной де-факто, то уже давно бы рулили конструкторы и кодогенераторы.
     
  10. im.

    im. Active Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    310
    rmn,
    Проектировать избегая подобных ситуаций, сразу заботится о зоне ответственности где память аллоцируется и где освобождается. Вот например есть gc_arena и gc_malloc в OpenSSL. Удобная вещь, есть рабочий участок, там создается garbage collector на входе, на выходе разрушается, внутри множественная работа с памятью, десятки аллоков. Ключевая процедура отработала - все разрушилось, и не надо следить за каждым отдельным указателем. Участков таких много, они небольшие. Зона ответственности четкая, заранее подумали.
     
  11. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Т.е. он при выходе все за нами молча подчистит и мы так и не узнаем, что наговнокодили и наоставляли висячих объектов? :)
     
  12. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    А зачем говнокодить и оставлять висячие объекты?
     
  13. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Речь не о том, что мы это делаем намеренно, а о том, что мы об этом можем даже не подозревать, пока наш хелловорлд не начнет десятки гигов памяти отжирать. Все эти сборщики мусора и "безопасные" функции - это как брызгать на себя духами, чтоб если и обосрешься, никто не заметит :)
     
  14. X-Shar

    X-Shar Active Member

    Публикаций:
    0
    Регистрация:
    24 фев 2017
    Сообщения:
    354
    В таком случае, нужно добавить 9-е правило в этой теме:

    9. Всегда проверяй параметры функции на робасность и возвращай коды ошибок из errno. В таком случае горе-кодер сможет понять, где накосячил и никакого бсода не нужно. :)

    Я немножко про другое хотел сказать, сейчас напишу более подробно, что хотел сказать в предыдущем посте.

    Во первых, если речь идет о критически важных каких-то системах, то в любом случае придется тратить деньги на тестирование и т.д., тут неважно кто разрабатывает систему.

    Скажу более, даже в РФ все такие системы подлежат обязательной сертификации, например вы не можете сказать "Я создал мега-бесопасную ось, ставьте ее например на самолет".

    Если нет сертификата, вы не можете продавать свой софт в этой сфере. Более того многие отрасли сертифицируют не софт, а изделие в целом, хотя никто не мешает вам производить только софт.

    Так-вот сертификация накладывает определенные требования и к разработке софта, которые будут проверятся аудиторами.

    Там много всего, вот например, если вы пользуетесь какими-то программами для тестов, эти программы тоже должны-быть сертифицированы. Либо проверять вручную.

    Так-вот отклонился я что-то от темы. Существуют несколько методик построения безопасного софта, НО в РФ как правило, делалось все вот-как:

    Собирается группа разработчиков, нужно сделать какую-то штуку. Группа программистов пишит код, который сами-же и разрабатывают, отлаживают и т.д.

    ОК, написали. Начинаются тесты, все хватаются за голову, что-же мы такое написали ! :) Часто еще и время выбирают этих тестов перед сдачей проекта, другова времени в принципе не находят.:)

    Про качество написанного кода я вообще молчу, в итоге получается тонна голого кода, нет не документации, не понятно что это и для чего. Если программист еще и дергает куски кода от куда-то, то вообще прощеп пристрелиться ! :)

    Как-же делают в тех-же штатах например:

    Архитекторы, это такие крутые чуваки, которые знают отрасль, проектируют систему, как "черный ящик", т.е. система должна делать то-то и то-то.

    Получается документ, далее уже не менее крутые чуваки, но уже кто приближен к разработки софта, начинают разбивать каждую задачу на подзадачи и расписывать каждую функцию либо псевдокодом, либо блоксхемами, ну либо техническим языком, как удобней кому.

    Вот например, архитектор сказал, нам нужна файловая система, которая состоит из ***

    Разработчик говорит, ОК. Нам нужны функции open, close, read, write. Которые делают то-то, имеет такие-то параметры, возвращают такие-то коды ошибоки т.д. Разумеется все это оформляется как документ.

    В таком случае кодеру, нужно-то всего-лишь, по этому документу закодить, причем добовлять что-то от себя запрещено.

    Да иногда может неполучится так сразу на бумаге разработать систему, поэтому часто проктекуют так-называемые прототипы софта, где разработчик отлаживает все, сам пишит код. Но потом прототип этот выкидывается, весь основной код пишится именно по проекту.

    Да в принципе и релизный код может писать либо разработчик, либо архитектор. Но т.к. в тех-же штатах, это не бедные люди, получают они не мало. А это уже доп. нагрузка на разработчика, ведь это нужно разработать код, задокументировать его, написать в положенном формате и стиле.

    Хотя если фирма не может себе позволить большей штат, то обычно разрабы сами и пишут релизный код. Но в таком случае реально можно просить двойную оплату. Поэтому многим дешевле нанять десяток индусов. :)

    Какие плюсы от такого подхода:

    1)У вас всегда будет задокументированный код.

    2)Такой проект легче тестировать. Т.к. тестировщик уже будет знать что от него хотят. Тесты пишутся относительно легко. По проекту.

    3)Новому человеку легче войти в проект. Т.к. есть от чего оттолкнуться.

    4)Расширять и переделывать такие проекты легче.

    Но есть минусы разумеется:

    1)Дороговизна такого подхода, вам нужен хороший штат сотрудников.

    2)Тратится больше времени, ведь пока разработчик создаст прототип. Пока задокументирует код и т.д.

    3)В случае ошибки в проекте, все переделывать и документы в частности, поэтому чем ошибка позже найдена, тем дороже она будет на стадии проекта. :dntknw:
     
  15. X-Shar

    X-Shar Active Member

    Публикаций:
    0
    Регистрация:
    24 фев 2017
    Сообщения:
    354
    Извиняюсь за огромный пост. Чот переборщил кажись. :crazy:
     
  16. im.

    im. Active Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    310
    Вам вряд ли уже что-то поможет, учитесь писать не говнокод.

    Возьмем например Windows NT, где для каждого процесса выделяются ресурсы и полностью освобождаются со смертью этого процесса. Это назовем зоной ответственности за ресурсы. Внутри отдельного приложения может быть говнокод и утечки памяти, но это не повлияет критически на стабильность всей ОС и соседних приложений. Умные люди пошли дальше и сделали зоны ответственности за ресурсы внутри программы для отдельных блоков. Таким образом удалось повысить стабильность приложения и получить отказоустойчивость при сбое отдельных компонентов.

    Речь идет об инструменте, который следует применять в наборе подходов.
    Здесь никто не ведет речь о волшебных пилюлях избавляющих от всех проблем.
    Если человек идиот, то ему никакие инструменты не помогут ))
     
  17. im.

    im. Active Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    310
    Я думаю здесь стоило бы поставить в пример опыт Toyota Production System из 14 принципов.
    Есть например там такая вещь как ротация кадров по производству, чтобы каждый сотрудник хорошо ознакомился с работой других специальностей.
    Именно от туда пошли такие понятия как Кайдзен, Канбан и пр.
    Нормальный подход подразумевает тесное сотрудничество между всеми участниками, тут однажды в компании Honda ребята сделали классный дизайн, а специалисты по эародинамике сделали классную аэродинамику с готовым дизайном и получился Honda Accord 9, ужасный автомобиль по внешнему виду, зато "архитекторы написали требования" и "программисты выполнили". В Toyota и Mercedes дизайнеры сотрудничают со спецами по аэродинамике и их модный дизайн отвечает одновременно и хорошей аэродинамике (одна из лучших у Mercedes). Это наглядная разница, достаточно посмотреть на внешний вид автомобилей, чтобы понять как должно быть.
    Вот мы сегодня имеем массу приложений построенных по принципам конструктора из фреймворков, когда на 4х ядерных телефонах тормозит какой-нибудь скролл текста ))

    Жесткие иерархии на предприятиях до добра не доводят, это отдельная крайность противоположная полному хаосу, истина где-то посередине.
    P.S. Все сотрудники должны взаимодействовать и иметь квалификацию.
    Архитекторы должен знать о кодинге, а кодеры об архтектуре.
    Идея с индусами, ну это гиблое дело, очевидно же и примеры имеются.
     
    X-Shar нравится это.
  18. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    X_Shar, вы привели две разные модели разработки (отечественная и зарубежная), реализующие общую так называемую концепцию Waterfall.
    При Waterfall у проекта всегда есть фиксированные стадии: проектирование, разработка, тестирование, внедрение и поддержка.

    Подход (наш и заграгичный) резко различается ввиду особенностей ведения бизнеса.

    В отечественном варианте все хотят почему-то найти широкопрофильного специалиста за малую сумму. То есть, платить зарплату в 2-3 раза ниже рынка, при этом иметь солидный выхлоп, чтобы человек мог 10 и более проектов одновременно тянуть. Потому что рынок стагнирует, процветает ещё не до конца сдохший совок и кумовство в руководстве, а продукты востребованы разве что в сфере госраспила. Каноничный пример:
    https://pravda-sotrudnikov.ru/company/tranzas-avivciya

    В заграничном варианте работодателю обычно нет вообще никаких проблем платить ЗП узкопрофильному специалисту. При чём, чем уже профиль, тем больше ЗП готовы платить. Потому что рынок развивается, продукты продаются, развитие фирмы идёт.

    Но помимо Waterfall есть ещё и другие способы ведения проектов. Например, Agile, когда есть потребность в продукте, а общего видения продукта нет, в том числе по причине массовости продукта. Разработка ведётся по принципу "сделать наиболее востребованный функционал в ближайшее время, а всякие свистелки и перделки - потом". Отсюда и возникают такие два столпа разработки как SCRUM и Kanban, когда небольшие команды спецов пилят определённые части продукта. В этом случае все стадии проектирования, разработки, тестирования, внедрения и поддержки смешаны воедино.

    Недостаток - человек полностью занят только в одном проекте, что для нашего пост-совка совсем неприемлемо.
     
    X-Shar нравится это.
  19. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Это три пункта. Тестирование по входу и внутреннее тестирование и возврат кода ошибки.
    MIRC требует что-бы вместо исключений функция возвращала код ошибки.

    Да видел я этот стандарт КТ-178В там окромя требования разделить всё и вся нет ничего. Более того большинство требований закрывается бумажками с двумя подписями без каких либо реальных действий.

    Да там защита от честных людей.
    Вот с этим не согласен. Изменение требует скорректировать и всю документацию. А ведь её должны проверить с 10 человек. Поэтому изменить в проекте можно только путем создания нового проекта. За исключения небольших правок.

    В своей отрасли ещё не одной задокументированной программы не видел.

    Я тут молча сижу и завидую заказчику. У заказчика 10 человек каждый со своей специализацией аналитик, тестер, дизайнер, несколько программистов. Я у себя на работе "царь и бог" и архитектуру пишу и тестирую и документацию рисую и пишу ещё и контрагентов пинаю. Сейчас вот на аттестацию буду сдаваться.

    Состав функций может определить разработчик. Только он и не кто иной. Так что все эти архитекторы вынуждены спускать документацию вниз и ждать пока разработчик ответить.
    Тут стоит понимать разницу в структуре управления в России и на западе. Там Архитектор и здесь архитектор это разные должности, как и куратор. Вы посмотрите большинство стандартов там написано для большого менеджмента, а не для исполнителей которому дают вольную.
     
    RET и X-Shar нравится это.
  20. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Как же я научусь, если буду постоянно использовать фреймворки умных дядей, которые маскируют мои ошибки?
     
    RET нравится это.