LINUX.ORG.RU

Анонсирован первый конкурс недобросовестного программирования на Rust

 


4

9

Команда Rust анонсирует первый ежегодный конкурс «недобросовестного Rust» по мотивам существующих конкурсов «недобросовестного C» и «недобросовестной криптографии».

Задача Rust — сделать доступным написание безопасного низкоуровневого кода, защищённого от случайных уязвимостей. Меньше времени уделяется возможности Rust защитить от умышленного внедрения уязвимостей при бдительном обзоре кода. Конкурс предназначен для обнаружения и устранения возможных слабостей языка и его экосистемы. Иными словами, авторы просят вас сломать систему с помощью достаточно лёгкого для понимания кода. Можете ли вы написать полностью safe-Rust, скрывающий логический баг, или скрыть в unsafe-Rust уязвимость, которая не обнаружится при обзоре кода?

>>> Подробности

anonymous

Проверено: Shaman007 ()
Последнее исправление: sudopacman (всего исправлений: 2)
Ответ на: комментарий от RazrFalcon

Да что-то я слабо уверен, что он откусит кусок десктопного пирога... но речь не про это.

Но ладно, десктоп так десктоп.

Mozilla запилила Rust, так давайте её творения и посмотрим: кусочки rust в Firefox (хотя ладно, тут биндинги), Servo (другие проекты и POC в большей или меньшей степени) - тут уже интереснее.

И да, сам Rust и Cargo не в счёт ;-)

Ну и ещё примеров (где лучше, где хуже): TLS 1.2 implementation, NES emulator.

В общем, то, что есть явный unsafe - это круто, не спорю, не спорил и спорить не буду. Но, надеюсь, я обосновал своё:

а unsafe не так редко нужен, как хотелось бы

h4tr3d ★★★★★
()
Последнее исправление: h4tr3d (всего исправлений: 1)
Ответ на: комментарий от anonymous

Человеческий мозг — говно, когда нужна точность и надёжность.

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

q0tw4 ★★★★
()
Ответ на: комментарий от h4tr3d

Servo

Так вы почитайте внимательно код по ссылке. Там половина - это флаги типа #![deny(unsafe_code)] и #[allow(unsafe_code)]. А вторая половина - это внутренности контейнеров, которые и не запрещают писать с unsafe. Они изолированны и протестированы. Конечный пользователь получает доступ только к safe коду.

другие

Аж три! Один в реализации контейнера, приватный код. Один с пометкой FIXME. И один вообще в бенчмарке, а значит не считается.

проекты

Аж один! И это безопасная микро-оптимизация, ибо авторы уже знают, что у них 100% utf8 и заново его проверять не нужно. String::from_utf8(string_bytes) по умолчанию производит валидацию utf8, что затратно.

POC

Большая часть биндинги.

меньшей

Вообще 0.

сам Rust

Это компилятор + std. Тут не удивительно.

и Cargo

Аж 11! И большая часть биндинги.

TLS 1.2 implementation

Аж 2!

NES emulator.

Аж 5! И всё биндинги.

И это в противовес С/С++ коду, который на 100% небезопасен.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

у меня 4-е проекта на Rust

Ого сколько SVG. А вы ему где-то применение находите или чисто для фана? Просто кроме inkskape больше нигде не видел реальных применений SVG

makoven ★★★★★
()
Ответ на: комментарий от makoven

Просто кроме inkskape больше нигде не видел реальных применений SVG

pokerface.bmp

Полно его, особенно в вебе. Если вы не видите - это не значит, что его нет. У меня на компе 60к SVG файлов для тестов, уж поверьте - нужная штука.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

Если вы не видите - это не значит, что его нет

Я и не спорю) Потому и попросил привести примеры где он применяется

makoven ★★★★★
()

авторы просят вас сломать систему с помощью достаточно легкого для понимания кода.

Могу сломать любую систему с помощью молотка, электропилы или достаточно большого куска камня. :-)

anonymous
()
Ответ на: комментарий от makoven

Картинки - по сути, самый популярный контент в сети. Любые способы сократить на них полосу пропускания полезны. SVG, в частности, неслабо облегчает всякие баннеры/логотипы.

anonymous
()
Ответ на: комментарий от h4tr3d

Я с этого и начал: «если мысленно ввести понятия safe/unsafe, то...».

Ага, но я всё равно не согласен (или не понимаю почему) «большая часть кода будет unsafe».

DarkEld3r ★★★★★
()
Ответ на: комментарий от q0tw4

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

А что это даст? Всё равно придётся обмазываться «подсказками анализатору» (типами) и/или аннотациями «вот тут предупреждений не надо» (unsafe). Разве что будет проще игнорировать это всё, если оно не встроено в компилятор, причём в виде ошибок.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Всё равно придётся обмазываться «подсказками анализатору» (типами)

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

«вот тут предупреждений не надо» (unsafe)

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

q0tw4 ★★★★
()
Последнее исправление: q0tw4 (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Так или иначе, оно там присутствует, уж по какой причине - вопрос вторичный или просто обойтись возможности нет, или от незнания/неумения (гм...), или же нужна оптимизация, которую иначе не получишь, или так проще (гм... для тестов?), или...

Первое же впечатление: чем сложнее и больше проект, тем тяжелее обходиться без unsafe. Хотя в простых проектах и на других языках косячить тяжелее, ну, если только очень захотеть. Но если кто-то хочет самобиться, путём отстрела головы через анус, вряд ли кто-то ему сможет это помешать сделать.

И это в противовес С/С++ коду, который на 100% небезопасен.

Ага. Я выше писал.

h4tr3d ★★★★★
()
Ответ на: комментарий от RazrFalcon

И? :) у меня один (или три? так вышло, что реюз получается делать очень удачно) проект рабочий, на базе которого построено уже 3 продукта (линейка AV.io) и начался третий, суммарно около 50К строк Modern C++ (к сожалению только C++11) кода в рамках ~300кб на код и данные, 128кб на кучу и где-то 96кб на DMA. И ни единого unsafe :-D

А если серьёзно, то практически удалось добиться формулы: компилируется == работает. И сроки не протухли, даже с запасом успелось. А 4К продукту и конкуренты слились (Inogeni, Magawell). И не было ни одной проблемы связанной с использованием памяти или каких-то C++-специфичных нюансов. В основном логика или косяки в понимании (или в самой) документации.

Ну и возвращаясь к нашим баранам: в тех нескольких проектах, в которые заглянул, так или иначе встречалось использованием unsafe. В нескольких оно отсутствовало вообще (два их трёх популярных HTTP фреймворков). О чём это говорит? Правильно: хреновая выборка :-D Но по мне, так если бы среди ссылок выше только пара использовала unsafe, а остальные были бы кристально чистыми, то моё бы высказывание выше можно было бы считать опровергнутым, ибо оправдание «да мне только для биндинга», звучит почти как «я присуну, ну на пол шишечки, а?». Раз не можешь обойтись в какой-то ситуации, значит нужен.

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

h4tr3d ★★★★★
()
Ответ на: комментарий от RazrFalcon

у меня 4-е проекта на Rust, суммарно под 12К строк. И ни единого unsafe. Как так?

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

NextGenenration ★★
()
Ответ на: комментарий от h4tr3d

суммарно около 50К строк Modern C++
И ни единого unsafe

весь код и есть один большой unsafe

NextGenenration ★★
()
Ответ на: комментарий от DarkEld3r

Эх, одной строкой, что может на ровном месте случиться:

  • нежелание использовать RAII для захвата и владения ресусом (будь то мутекс, память или какой-то хендл) может привести к интересным артефактам в случае исключения или случайного return, последнее ревью в QtC, где я принимал участие, вылилось в 4 замечания на утечки памяти.
  • конструкторы копирования и операторы присваивания по умолчанию для всех объектов, могут вылиться боком, если объект владеет каким-то ресурсом, который освобождается в деструкторе
  • обратиться из конструктора одного глобального объекта к другому, вне единицы трансляции
  • strict aliasing, для полной гарантии ты должен сделать memcpy из одной области памяти в другую. Этого практически никто не делает, так все компиляторы сейчас входят в положение и прощают. А всегда ли так будет?
  • обратиться к виртуальному методу из конструктора
  • выбросить или не поймать исключение в деструкторе (посмотри в скольки проектах в деструкторе try стоит ;-))
  • использование указателей в интерфейсах для пользователя библиотеки
  • выделение/освобождение памяти в DLL/SharedObject и основном приложении
  • кто-то в списке инициализации бросил исключение
  • ...
  • я спать.
h4tr3d ★★★★★
()
Ответ на: комментарий от h4tr3d

Дык, если фантазировать о safe/unsafe в плюсах, то часть вопросов тоже можно порешать запретив определённые действия.

кто-то в списке инициализации бросил исключение

А тут в чём проблема?

А ещё тебя, возможно, удивит, но в расте утечки памяти не считаются «нарушением безопасности». Более того, можно даже написать так:

let a = Box::new(...);
drop(a); // Утечка и даже никакого unsafe

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

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

q0tw4 ★★★★
()
Ответ на: комментарий от anonymous

Может std::mem::forget?

Да, именно так. (:

В общем, не даёт мне покоя этот forget. Понятное дело, что и при помощи циклических ссылок можно «безопасно» утечку устроить, но было как-то спокойнее, когда forget был unsafe.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

В растономиконе этому фогету и подобным фичам глава посвящена.

khrundel ★★★★
()
Ответ на: комментарий от anonymous

Ну в расте есть трюк с lifetime как часть типа. Простой и элегантный ход, позволяющий внеся минимум сущностей свести казалось бы творческую и неописуемую формально задачу слежения за дисциплинами доступа и владения данными к элементарным математическим проверкам при компиляции. Да, получилось конечно не идеально, без unsafe тот же refcounter не напишешь, но для многих даже больших задач вполне приемлемо. Мало того, в агде, например, даже зацикливание программы недопустимо на уровне типов, если не включить флаг игнора для этой фичи (в результате не только неполнота по Тьюрингу, так еще и усложняется жизнь кодера на порядки). Вот я и спрашиваю, а можно ли ввести некое свойство типа, позволяющее в компилтайме отслеживать утечки памяти на указателях? Надо бы внимательно почитать второй том Пирса, там вроде что-то про ресурсменеджмент в типах было.

q0tw4 ★★★★
()
Последнее исправление: q0tw4 (всего исправлений: 1)
Ответ на: комментарий от h4tr3d

Необходимости в unsafe - нет. В большинстве случаев можно обойтись без него. Хочешь используй, хочешь - нет.

RazrFalcon ★★★★★
()
Ответ на: комментарий от q0tw4

1 глобальный вектор, добавляем туда шаредные ссылки и забываем удалять вуаля, формально утечки нет, фактически память течёт. Или берём реализацию счётчика ссылок с поддержкой слабых ссылок: стандартная реализация подразумевает 2 счётчика в управляющем блоке и удаление этого блока только после исчезновения всех, включая слабые, указателей на блок. Но чтоб увеличить производительность, управляющий блок и сам объект выделяют одним махом. Соответственно, храня где-то в кафе слабый указатель но большой буфер данных можно создать утечку.

khrundel ★★★★
()

или скрыть уязвимость в unsafe-Rust которая не обнаружится при обзоре кода?

Будущие офицеры NSA.

pacify ★★★★★
()
Ответ на: комментарий от khrundel

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

q0tw4 ★★★★
()
Ответ на: комментарий от q0tw4

Ну вот и получается, что с утечками может помочь только эвристический анализатор кода

только эвристический анализатор

Не получается.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Ну то что сейчас запилено в расте тоже помощник контроля памяти. Когда умирает хозяин, все его данные деструктятся и все такое. Но один forget легко и непринужденно рушит всё. И ни одна скотина не предупредит, что у вас в коде левый forget почистить забыли или что-то вроде него.

q0tw4 ★★★★
()
Ответ на: комментарий от q0tw4

с утечками может помочь только эвристический анализатор кода

Не получается.

Ну то что сейчас запилено в расте тоже помощник контроля памяти

И ведь он помогает. Хотя не является «эвристическим анализатором кода».

один forget легко и непринужденно рушит всё

Расскажи подробнее, что именно он рушит.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Ладно, forget случайно врядли заваляется в коде как например тот же unwrap, который будучи забыт в коде приводит к неожиданному завершению программы. Это был просто теоретический контрпример, о том что можно написать программу на safe расте, которая неограниченно накапливает недоступную память, на 100% подходящую под определение утечки памяти.

Рассмотрим реальный пример с кешем. Есть допустим некий кеш данных. Данные туда кладутся кладутся, но код очистки кеша то ли не написан, то ли просто лажает и со временем в кеше накапливаются старые данные, вероятность повторного использования которых стремится к нулю. Итак как в таком случае раст предупредит про утечку памяти? Никак. А эвристический алгоритм скорее всего вообще выдаст ошибку компиляции с текстом: «Потенциально неограниченное использование памяти в задаче, реализуемой в рамках ограниченной памяти» и укажет на то, что если добавить проверку на переполнение и в случае такового удалять данные из кеша, корректность программы не нарушится. При этом если задача например требует експоненциального размера памяти, то вместо ошибки будет просто предупреждение о высокой вероятности OUT_OF_MEMORY, но скомпилить разрешит. Вобщем это компилятор из серии тех, которые выдают ошибку «Неефективный алгоритм» на код сортировки пузырьком, и достичь такого типами невозможно.

q0tw4 ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.