Size: a a a

2021 July 15
Блог*
CVE-2021-22555: Turning \x00\x00 into 10000$

Радует, что комбинации байтов несчётны, всегда весело будет.

https://google.github.io/security-research/pocs/linux/cve-2021-22555/writeup.html
источник
Блог*
#gamedev

У Озкриффа Земерот вышел в ранний доступ в Google Play!
Telegram
ozkriff.games
# Android: Открытое тестирование в Google Play

Федиными стараниями по портированию (и щепоткой моей возни с гугловой админкой) Земерот таки добрался до раннего доступа в Google Play, ура! 🎉

https://play.google.com/store/apps/details?id=rust.zemeroth

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

Вообще, это около недели назад еще случилось, но чего-то мне некогда было эту новость до телеги дотащить - кое-какие всплывшие ошибки уже получилось поправить, расскажу об этом в следующих постах. И да, это хороший знако потихоньку сворачивать свой отпуск от растогеймдева и пробовать опять влиться в процесс. Клац-клац.
источник
Блог*
Как я дошла до того, что доказываю, что «шо» звучит очень няшно?..
источник
Блог*
"Шо" не звучит няшно, change my mind
источник
Блог*
#rust и тут просится ещё какой-то хештег, только я не знаю, какой
источник
Блог*
источник
2021 July 16
Блог*
#meme

И ведь немного жаль, что такого не будет
источник
Блог*
источник
2021 July 17
Блог*
#meme
источник
Блог*
Что делает @insert_reference_here, когда у него освобождается свободное время в выходные? Ну разумеется решает чужую заковыристую задачку с macro_rules!.
источник
2021 July 18
Блог*
joy/ #interestingasfuck
Извлечение электричества из катушки Теслы с помощью шприца
источник
Блог*
#rust #gamedev

У Zemeroth число звёздочек на гитхабе перевалило за тысячу, ю-ху! 🥳

https://t.me/ozkriff_games/32
источник
2021 July 19
Блог*
#prog #rust

Хозяйке на заметку

Как известно, в macro_rules! можно использовать спецификатор повтора ? в форме $(some complex pattern)?. Вопрос: что делать, если опицональный захват нужно развернуть в Some($захват), если он есть, и в None, если его нету? Очень просто: достаточно делегировать эту задачу очень простому макросу make_option!:

macro_rules! make_option {
   () => { ::core::option::Option::None };
   ($($anything:tt)*) => { ::core::option::Option::Some($($anything)*) };
}

Разумеется, это будет работать без сбоев только в том случае, если захват не может соответствовать пустой последовательности лексем.
источник
Блог*
#itsec #article

И да, извините, что в этот раз не прочитал статью целиком (пока). Одним из уязвимых мест оказался парсер изображений. Сложный парсинг, который запускается на недоверенных данных и потому может стать вектором хакерской атаки — просто идеальный юзкейс для Rust.
источник
Блог*
Извините, что ночью, но исследователи утверждают, что Pegasus стабильно взламывает самую последнюю версию айфона (14.6). Без всяких кликов по ссылкам, просто посылают жертве «заряженную смску» (сообщение в iMessage) и всё, атакующий владеет телефоном.

Речь идет об использовании уязвимости нулевого дня, о которой пока не знает Apple. Благодаря этому, атакующие могут даже не сохранять взлом в долгосрочной памяти, так что после перезагрузки телефона почти все следы атаки стираются — будет нужно, взломают ещё раз. Это усложняет исследование.

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

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

Если вы интересны спецслужбам — выключите iMessage в настройках айфона.
источник
2021 July 20
Блог*
#prog #rust #моё

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

Начнём с определения центральной структуры для разбора:

#[derive(Clone)]
struct Lexer<'a> {
   s: &'a str,
}

impl<'a> Lexer<'a> {
   fn of(s: &'a str) -> Self {
       Self { s }
   }
}

Да, всё верно, это буквально обёртка над строковым слайсом. Все последующие методы будут принимать мутабельную ссылку на Lexer и будут возвращать Option<Something>, где Some означает, что нечто удалось распарсить, а None будет обозначать ошибку. При этом все эти методы будут следовать одному правилу: если что-то распарсить не удалось, то Lexer остаётся ровно в том же состоянии, что был до вызова.

Начнём с метода, который будет обозначать конец разбора — он пригодится нам, чтобы удостовериться, что мы не оставили никакого мусора:

fn end(&mut self) -> Option<()> {
   if self.s.is_empty() {
       Some(())
   } else {
       None
   }
}

Следующий метод не очень полезен сам по себе, но он потребуется для других методов. Он просто будет сдвигать позицию, с которой производится парсинг:

fn shift(&mut self, pos: usize) {
   self.s = &self.s[pos..];
}

Что ж, теперь напишем самый простой метод, который действительно что-то парсит, а именно — конкретную переданную строку:

fn literal(&mut self, literal: &str) -> Option<()> {
   self.s = self.s.strip_prefix(literal)?;
   Some(())
}

Не менее полезным будет метод, который возвращает то, что находится до переданной строки:

fn before_literal(&mut self, literal: &str) -> Option<&'a str> {
   let pos = self.s.find(literal)?;
   let ret = &self.s[..pos];
   self.shift(pos + literal.len());
   Some(ret)
}

Ну и первый метод, который делает по настоящему нетривиальный разбор: парсинг беззнакового числа:

fn number<Num: std::str::FromStr>(&mut self) -> Option<Num> {
   let pos = self
       .s
       .as_bytes()
       .iter()
       .position(|ch| !ch.is_ascii_digit())
       .unwrap_or(self.s.len());
   let ret = self.s[..pos].parse().ok()?;
   self.shift(pos);
   Some(ret)
}

Clippy тут, к сожалению, ругается на вызов .unwrap_or(self.s.len())... Точнее, ругался раньше, теперь это исправили. Отлично!

Казалось бы, что можно сделать с таким набором методов? Ну, этого уже достаточно, чтобы распарсить IPv4-адрес:

#[derive(PartialEq, Debug)]
struct Ip4Addr([u8; 4]);

fn parse_ip(s: &str) -> Option<Ip4Addr> {
   let mut p = Lexer::of(s);
   let a = p.number()?;
   p.literal(".")?;
   let b = p.number()?;
   p.literal(".")?;
   let c = p.number()?;
   p.literal(".")?;
   let d = p.number()?;
   p.end()?;
   Some(Ip4Addr([a, b, c, d]))
}

fn main() {
   assert_eq!(parse_ip("12.32.200.21"), Some(Ip4Addr([12, 32, 200, 21])));
}

Обратите внимание, благодаря выводу типов нам не пришлось уточнять тип для p.number().

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

fn optional<T, F: FnOnce(&mut Self) -> Option<T>>(&mut self, f: F) -> Option<T> {
   let backtrack = self.clone();
   let ret = f(self);
   if ret.is_none() {
       *self = backtrack;
   }
   ret
}

В принципе, теперь мы можем распарсить IP4-адрес с опциональной маской подсети, но я покажу кое-что более интересное: парсинг из задачи Advent of Code 2020.
источник
Блог*
Частью решения является разбор строк вида:

bright white bags contain 1 shiny gold bag.
vibrant plum bags contain 5 faded blue bags, 6 dotted black bags.
faded blue bags contain no other bags.

Напишем функцию для разбора одной подобной строки:

fn parse_bags_with_amount(line: &str) -> Option<(&str, Vec<(&str, usize)>)> {
   let mut p = Lexer::of(line);
   // ...

Повторяющимся элементом каждой строки является подстрока "bags contain". Извлечём то, что находится до этой строки — это и будет цветом сумки, про содержимое которой идёт речь:

    let outer_color = p.before_literal(" bags contain ")?;

А вот теперь возможны варианты. Если далее идёт "no other bags.", то на этом можно разбор заканчивать и возвращать пустой список:

    if p.optional(|p| {
       p.literal("no other bags.")?;
       p.end()
   })
   .is_some()
   {
       return Some((outer_color, Vec::new()));
   }

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

    let mut inner_colors = Vec::new();
   loop {
       // ...
       if p.optional(|p| p.literal(", ")).is_none() {
           break;
       }
   }

Тут бы пригодился цикл с постусловием, которого в Rust, увы,  нету :/

Теперь нам нужно извлечь число сумок, их цвет и само слово bag, учтя при это, что оно может быть во множественном числе:

        // ...
       let amount = p.number()?;
       let inner_color = p.before_literal(" bag")?.trim_start_matches(' ');
       p.optional(|p| p.literal("s"));
       inner_colors.push((inner_color, amount));
       // ...

Строка заканчивается точкой:

    p.literal(".")?;
   p.end()?;

Если выполнение дошло до этой точки, значит, парсинг успешен:

Some((outer_color, inner_colors))

Проверим, как оно работает:

fn main() {
   let input = "\
bright white bags contain 1 shiny gold bag.
vibrant plum bags contain 5 faded blue bags, 6 dotted black bags.
faded blue bags contain no other bags.";
   let parsed = input
       .lines()
       .map(parse_bags_with_amount)
       .map(Option::unwrap)
       .collect::<Vec<_>>();
   assert_eq!(
       parsed,
       [
           ("bright white", vec![("shiny gold", 1)]),
           ("vibrant plum", vec![("faded blue", 5), ("dotted black", 6)]),
           ("faded blue", vec![]),
       ],
   );
}

Работает! Как всегда, весь код в гисте. Как вы могли заметить, техника не самая изящная, но вместе с тем она достаточно простая, чтобы её при случае, когда требуется быстро написать парсер, его можно было бы написать руками вот прямо сейчас — как я, собственно, тогда и сделал.
источник
Блог*
The internet is for porn cats, так что держите котика
источник
Блог*
Которепости і підписюни (2)
источник
2021 July 21
Блог*
Уведомление по почте в час ночи: "Ваш MR [который уже пару месяцев пилится и совсем недавно пришёл в состояние, пригодное для аппрува] теперь нельзя смержить из-за конфликтов".

Кто, блин, пушает код в рабочую репу в такое время?

#трудовыебудни
источник