LINUX.ORG.RU

В Rust borrow checker обнаружены ошибки, существовавшие 11 лет и позволяющие обращаться к освобождённой памяти

 , ,


1

5

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

В качестве примера кода, демонстрирующего ошибку, приведён (ссылка на Rust playground; для запуска нужно нажать кнопку “Run”):

struct Q<T, F: FnMut(&T)>(Option<T>, F);

impl<T, F: FnMut(&T)> Drop for Q<T, F> {
    fn drop(&mut self) {
        self.1(self.0.as_ref().unwrap())
    }
}

fn main() {
    let mut out: Option<&'static _> = None;
    {
        let l = vec![vec![1]];
        let mut q = Q(None, |s| {
            out = Some(*s);
        });
        q.0 = Some(&l);
    }
    println!("{:?}", out);
}

Обнаружение unsoundness (ошибок, приводящих к нарушению гарантий компилятора) в borrow checker’е Rust — не самое необычное явление. Но эта ошибка примечательна тем, насколько простым может быть код, вызывающий её. Для других ошибок приходилось сильно изворачиваться, чтобы избежать проверок компилятора.

Ссылка на issue: https://github.com/rust-lang/rust/issues/164250

★★

Последнее исправление: shdown (всего исправлений: 2)

Для не сильно знакомых с rust - это тот самый «выстрел в ногу»?

gruy ★★★★★
()

интересно откоментенное по коду пояснение хака и момент когда происходит выход за гарантии борова

qulinxao3 ★☆
()

ну да !! этожъ элементарный кодъ !!
имхо лучше написать «малогабаритный код», «влезающий на один экран»…
высказывания на языке высшей математики или регекспы тоже малогабаритны, но ни хрена не элементарны :)

пересахарить код не всякий сможет :)

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 1)

Ссылка на issue: https://github.com/rust-lang/rust/issues/164250

Хех, закрыли комментарии с формулировкой «We’re preventively locking this issue to prevent spam and other unhelpful comments», где разных вариантов кода для проверки возникновения этой проблемы уже накидали (самое раннее где зафиксировали срабатывание - на релизе 1.4 от 2015г)

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

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

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

Ну так на то ты и не программист, чтобы даже простейший синтаксис тебе выглядел непонятно

Я - программист, синтаксис непонятный. Понятный, конечно, только говно. Не ясно зачем применено слово for: можно же было ещё какой знак применить, или на клавиатуре уже кончились?

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

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

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

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

Создатели Rust'а осознанно выбрали выразительность вместо псевдокодовости.

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

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

проблема не баге

проблема в речекраканье предшествующих лет что раст гарантированно при не использование unsafe - не течёт памятью

а оказывается всё как всегда

маркетинг важнее доказанности (котороя если и есть то явно уже)

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

Вы не понимаете в чём суть borrow checker'а.

А суть в том, что он реально предотвращает возникновение ряда ошибок. И даже если этот ряд не совсем полный, то он всё равно довольно большой. Так что, это всё в любом случае реально работает на практике.

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

суть в том, что он реально предотвращает возникновение ряда ошибок

Чел, не позорь себя и раст, а? (себя-то хрен с ним, конечно…)

Ну новость же реально показывает, что не предотвращает. Точнее «не всегда», как оказалось.

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

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

Вы неправильно читаете что я пишу.

Люди высмеивают Rust исходя из ложной предпосылки. Как в одной из тем тут кто-то писал «Разве Rust спроектирован не так, чтобы из любого говна делать конфетку?». Типа, про него говорят, что в нём вообще ошибки невозможны.

А никто этого и не утверждал, и я на это и указываю.

Да, в Rust возможны ошибки. Но не все.

Отсутствие определённого ряда ошибок - это реальная фича Rust'а.

А насколько этот ряд полный - это уже второй вопрос.

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

деточка

тут оказывается до Leak Апоплексии (в 2015) Rust’форсеры утверждали что у них математически доказанная невозможность утечки(то биш захвата и не возврата в пулл)уже переставшей быть нужной памяти - оказалось это не так - после этого утверждение сменилось на то что не возможно получить доступ к уже освобождённой памяти ( очевидно в этом абзаце речь про не unsafe блоки)

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

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

тут оказывается до Leak Апоплексии (в 2015) Rust’форсеры утверждали что у них математически доказанная невозможность утечки(то биш захвата и не возврата в пулл)уже переставшей быть нужной памяти

Это где? Вроде как очевидно, что reference counting (Rc, Arc) не может собирать циклические ссылки.

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

Когда введут новое ключевое слово safe, которое окончательно сделает все безопасным?

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

«ненаю» - запоищи «Leakpocalypse» (2015) - реальная печаль что это(случившееся в 2015 в частности переопределение в рамках языка какая же семантика у safe ) чистый речекряк - ради маркетинга прям по классике шеклевского Билета на планету Транай - где нет преступности(а есть добровольное лицензированое мытарство), нет попрошаек (есть лицензированая деятельность по сбору пожертвований) -

так что то что раст придаёт уверенности - ну прям как электролиты в Идиократии

qulinxao3 ★☆
()
Р Е Ш Е Т О !
Е Ш Е Т О ! Р
Ш Е Т О ! Р Е
Е Т О ! Р Е Ш
Т О ! Р Е Ш Е
О ! Р Е Ш Е Т
! Р Е Ш Е Т О
thunar ★★★★★
()
Ответ на: комментарий от neumond

Насколько я понимаю эту программу на Rust, эквивалентный код будет примерно таким (указатели, потому что в C++ ссылка не может быть NULL и ссылки нельзя присваивать):

#include <vector>
#include <optional>
#include <functional>
#include <iostream>

template<class T> struct Q : public std::pair<std::optional<T>, std::function<void(T&)>> {
    using std::pair<std::optional<T>, std::function<void(T&)>>::pair;

    ~Q() {
        this->second(this->first.value());
    }
};

int main() {
    std::optional<std::vector<std::vector<int>> *> out = std::nullopt;
    {
        auto l = std::vector<std::vector<int>>{std::vector<int>{1}};
        Q<std::vector<std::vector<int>> *> q = {std::nullopt, [&](auto &s) {
            out = s;
        }};
        q.first = &l;
    }
    std::cout << out.value()[0][0][0] << std::endl;
}

Не считая #include, столько же строк.

shdown ★★
() автор топика
Последнее исправление: shdown (всего исправлений: 4)
Ответ на: комментарий от saahriktu

Вы неправильно читаете что я пишу.

Я читаю то, что написано. В голову залезть не могу.

Люди высмеивают Rust исходя из ложной предпосылки. Как в одной из тем тут кто-то писал «Разве Rust спроектирован не так, чтобы из любого говна делать конфетку?». Типа, про него говорят, что в нём вообще ошибки невозможны.

Я не вижу смысла комментировать таких идиотов. Поставил клоуна, да пошёл дальше. Самостоятельно потом делать хорошую мину при плохой игре для раста — контрпродуктивно.

А никто этого и не утверждал, и я на это и указываю.

Лучше не указывать никак, чем так, как это сделал выше ты. При том, что в целом посыл правильный.

Да, в Rust возможны ошибки. Но не все.

Отсутствие определённого ряда ошибок - это реальная фича Rust’а.

Ну вот опять пошла какая-то религиозная шиза.

Это было бы адекватно говорить в том случае, когда очередной неадекват «шутит» про «зато безопасно» в случае с растом, когда ошибка не касается гарантий, даваемых растом. Но тут-то… Тут именно те ошибки, от которых должен защищать раст. Это именно баг. Что ты несёшь?..

А насколько этот ряд полный - это уже второй вопрос.

Это не второй, не третий и даже не сотый вопрос, это вопрос вопиющей идиотии.

CrX ★★★★★
()

В Rust borrow checker обнаружены ошибки, существовавшие 11 лет и позволяющие обращаться к освобождённой памяти

Говорят боров не настоящий!

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

Мда... Мне это напоминает разговор с одним виндузятником более чем 20 лет назад, когда я только начал осваивать линуксы...

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

Но тот виндузятник сделал упор не на относительные единицы (как я), а на абсолютные.

Типа, баги всё равно везде есть, так что, мол, никакой разницы в этом смысле нет.

Так и тут...

Тут именно те ошибки

В теме речь про один баг. Всего один. Из наличия которого не следует вывод, что borrow checker с этим багом абсолютно бесполезен. Именно про это я и говорю.

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

Люди высмеивают Rust исходя из ложной предпосылки.

Это в твоей голове ложные предпосылки. Высмеивают как обычно: для приземления пафоса хайпожоров и просто обидного смеха.

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

Не, оно вообще ни в каком смысле не эквивалентно.

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

На практике, мой код сегфолтится, как и код на Rust, приведённый в ОП-посте. Твой код выводит что-то и не сегфолтится.

Наконец, если мой код «поправить» (вынести auto l = … за фигурные скобки), то он печатает число 1, а не указатель. Код на Rust, в теории, должен распечатать опциональный вектор векторов (в моём коде я сократил это до вывода первого значения первого вектора):

Some([[1]])

shdown ★★
() автор топика
Последнее исправление: shdown (всего исправлений: 5)
Ответ на: комментарий от saahriktu

Вы не понимаете в чём суть garbage collector’а.

А суть в том, что он реально предотвращает возникновение ряда ошибок. И даже если этот ряд не совсем полный, то он всё равно довольно большой. Так что, это всё в любом случае реально работает на практике.

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

Мда… Мне это напоминает разговор с одним виндузятником более чем 20 лет назад, когда я только начал осваивать линуксы…Я тогда радовался в т.ч. и по тому поводу, насколько стабильнее и безбажнее работают линуксы по сравнению с виндой. А багов в целом было на порядки меньше.Но тот виндузятник сделал упор не на относительные единицы (как я), а на абсолютные.Типа, баги всё равно везде есть, так что, мол, никакой разницы в этом смысле нет.Так и тут…

А я вот помню как-то на рыбалку ездил…

Какая же чушь, не имеющая отношения к обсуждаемой теме.

В теме речь про один баг. Всего один. Из наличия которого не следует вывод, что borrow checker с этим багом абсолютно бесполезен.

Совершенно верно. Но ты лично сделал всё, чтобы выставить его более нелепым, чем он является.

Именно про это я и говорю.

Если бы ещё адекватные вещи говорил, цены бы не было. Ты ж вообще-то раньше нормальным был, ну почти, кроме помешанности на «хрюникоде». Что ж такое случилось?..

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

Но ты лично сделал всё, чтобы выставить его более нелепым, чем он является.

Ещё раз: что я такого написал кроме утверждения о том, что сабжевый баг не превращает borrow checker в абсолютно бесполезную тыкву?

А borrow checker как раз и предназначен для предотвращения ошибок. Если он ничего не предотвращает - он тогда и есть абсолютно бесполезная тыква.

Если от него есть практическая польза, то он всё-таки что-то предотвращает. Пусть не сабжевый баг, но другое.

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

На практике, мой код сегфолтится,

У меня не сегфолится, а выводит примерно такое же число как и мой (адрес какого-то объекта из malloc). А чем ты компилировал? Не шлангом ли?

Наконец, если мой код «поправить» (вынести auto l = … за фигурные скобки), то он печатает число 1, а не указатель.

А да, если так сделать то выводит единицу.

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

Ещё раз: что я такого написал кроме утверждения о том, что сабжевый баг не превращает borrow checker в абсолютно бесполезную тыкву?

Да ничего. Просто иногда лучше ничего не написать, чем написать то, что выглядит максимально жалко. Впрочем, я уже понял, что мы друг друга в этом вопросе не поймём.

CrX ★★★★★
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария