en
Feedback
Сохранёнки программиста

Сохранёнки программиста

Open in Telegram

Заметки и ссылки на будущее, чтобы изучить когда будет время. Разместить рекламу: @tproger_sales_bot Правила общения: https://tprg.ru/rules Другие каналы: @tproger_channels Другие наши проекты: https://tprg.ru/med

Show more
6 538
Subscribers
-224 hours
-147 days
-5230 days
Attracting Subscribers
August '26
August '26
+23
in 0 channels
July '26
+26
in 3 channels
Get PRO
June '26
+48
in 2 channels
Get PRO
May '26
+70
in 0 channels
Get PRO
April '26
+30
in 0 channels
Get PRO
March '26
+47
in 5 channels
Get PRO
February '26
+57
in 14 channels
Get PRO
January '26
+38
in 2 channels
Get PRO
December '25
+46
in 4 channels
Get PRO
November '25
+45
in 2 channels
Get PRO
October '25
+40
in 7 channels
Get PRO
September '25
+26
in 3 channels
Get PRO
August '25
+41
in 1 channels
Get PRO
July '25
+46
in 0 channels
Get PRO
June '25
+38
in 2 channels
Get PRO
May '25
+68
in 5 channels
Get PRO
April '25
+49
in 1 channels
Get PRO
March '25
+63
in 1 channels
Get PRO
February '25
+69
in 2 channels
Get PRO
January '25
+72
in 4 channels
Get PRO
December '24
+46
in 1 channels
Get PRO
November '24
+104
in 6 channels
Get PRO
October '24
+73
in 4 channels
Get PRO
September '24
+87
in 3 channels
Get PRO
August '24
+204
in 4 channels
Get PRO
July '24
+86
in 4 channels
Get PRO
June '24
+77
in 4 channels
Get PRO
May '24
+75
in 4 channels
Get PRO
April '24
+68
in 3 channels
Get PRO
March '24
+65
in 4 channels
Get PRO
February '24
+50
in 0 channels
Get PRO
January '24
+64
in 1 channels
Get PRO
December '23
+59
in 2 channels
Get PRO
November '23
+3 534
in 33 channels
Get PRO
October '23
+55
in 1 channels
Get PRO
September '23
+71
in 0 channels
Get PRO
August '23
+69
in 0 channels
Get PRO
July '23
+57
in 0 channels
Get PRO
June '23
+180
in 0 channels
Get PRO
May '23
+73
in 0 channels
Get PRO
April '23
+93
in 0 channels
Get PRO
March '23
+65
in 0 channels
Get PRO
February '23
+113
in 0 channels
Get PRO
January '23
+68
in 0 channels
Get PRO
December '22
+86
in 0 channels
Get PRO
November '22
+90
in 0 channels
Get PRO
October '22
+117
in 0 channels
Get PRO
September '22
+134
in 0 channels
Get PRO
August '22
+787
in 0 channels
Get PRO
July '22
+119
in 0 channels
Get PRO
June '22
+90
in 0 channels
Get PRO
May '22
+157
in 0 channels
Get PRO
April '22
+131
in 0 channels
Get PRO
March '22
+117
in 0 channels
Get PRO
February '22
+198
in 0 channels
Get PRO
January '22
+149
in 0 channels
Get PRO
December '21
+5 099
in 0 channels
Get PRO
November '21
+927
in 0 channels
Get PRO
October '21
+1 849
in 0 channels
Date
Subscriber Growth
Mentions
Channels
26 August0
25 August0
24 August+1
23 August+2
22 August0
21 August0
20 August0
19 August0
18 August+2
17 August+1
16 August+1
15 August+2
14 August0
13 August+1
12 August0
11 August+3
10 August+3
09 August0
08 August+2
07 August+1
06 August0
05 August0
04 August0
03 August+2
02 August+2
01 August0
Channel Posts
На скриншоте ролик, к которому YouTube показывает пометку «снято камерой». Внутри — рендер из Big Buck Bunny. Дэвид Бьюкенен
На скриншоте ролик, к которому YouTube показывает пометку «снято камерой». Внутри — рендер из Big Buck Bunny. Дэвид Бьюкенен разобрал, почему C2PA на Android так подделывается. Приложения-камеры опираются на Key Attestation и Play Integrity, а рут, полученный через эксплойт, обе проверки не тревожит: загрузчик остаётся заблокированным, ключи AVB — вендорскими, и серверы Google спокойно выдают устройству ключи подписи. Сам ключ из StrongBox не вытащить, но попросить Titan M2 подписать произвольные данные рут может. Проверял автор на Pixel 8a и 9a, рут брал одноклик-эксплойтом CVE-2026-43499, который на полностью обновлённых Pixel всё ещё работает. Приложение Pixel Camera при этом имеет Assurance Level 2 — высший из определённых сейчас уровней программы соответствия C2PA. Google закрыла отчёт как «Won't fix (infeasible)», выплатила 7500 долларов, а плашка у ролика после публикации исчезла — автор считает, что её сняли руками. @prog_stuff

2
ELF — это база данных, которая отказывается в этом признаться: .strtab делает интернирование строк, .gnu.hash работает индекс
ELF — это база данных, которая отказывается в этом признаться: .strtab делает интернирование строк, .gnu.hash работает индексом, таблица заголовков секций — это таблица таблиц, а st_name — внешний ключ, разложенный руками. Фарид Закария довёл мысль до конца. Его прототип SELF — исполняемый файл, который целиком является базой SQLite: file hello показывает «SQLite 3.x database», ./hello печатает Hello, world!, а sqlite3 hello 'SELECT soname FROM ldd' отвечает libc.so.6. Запуск идёт через binfmt_misc и отдельный интерпретатор. Отсюда strip — это DELETE и VACUUM, patchelf — UPDATE, а LD_PRELOAD — строка в таблице, которую можно включить и откатить транзакцией. Цена: около 5 миллисекунд на старте и страницы, которые копируются из b-дерева вместо отображения в память. @prog_stuff
237
3
Как понять, что программисту пора в отпуск: — на столе бардак; — шорты не доставались с позапрошлого лета; — чудится тифлинг;
Как понять, что программисту пора в отпуск: — на столе бардак; — шорты не доставались с позапрошлого лета; — чудится тифлинг; — на вопрос «когда отдыхаешь?» отвечает «после релиза»; — релиз был в феврале. Сам он с места не сдвинется. Помогите Типичному Программисту собраться и улететь в отпуск в новой мини-игре!
270
4
Одна строка #define MICROPY_HW_ENABLE_RNG (0) отключила аппаратный генератор случайных чисел на STM32, и прошивка аппаратного кошелька молча перешла на слабый программный Yasmarang. Гостевой разбор на btc++ по мотивам истории с Coldcard показывает, как это осталось незамеченным. В коде видна попытка переопределить pyb_rng_get под собственный источник энтропии, рядом комментарий «у нас своя версия этого кода». Но make_new_wallet() вызывал random.bytes(32), а тот шёл другим путём, через rng_get(), и в итоге брал числа из генератора, который годится для игр, а не для ключей. Код исполнялся без ошибок и честно возвращал 32 байта. Отдельная часть текста про ревью: автор сравнивает обычный коммит на 15 строк и 235 символов описания с подозрительным изменением на 1534 строки и 5 символов в сообщении. Это независимый разбор, а не официальный отчёт Coldcard, о чём в тексте сказано прямо. @prog_stuff
270
5
В LLVM 23 время компиляции сократилось на 6,75 процента, а на sqlite3 — на 10,53. Никакого одного крупного изменения за этим
В LLVM 23 время компиляции сократилось на 6,75 процента, а на sqlite3 — на 10,53. Никакого одного крупного изменения за этим нет: Александр Энгельке собрал по частям, откуда взялись эти проценты. Хеш-таблицы перевели с квадратичного пробирования на линейное и избавились от ключей-надгробий: DenseMap дал −1,27 процента, SmallPtrSet −0,24, StringMap −0,10. Хеш-функцию сменили с CityHash на xxh3. В SmallVector путь роста вынесли из тела push_back, чтобы разрешить хвостовой вызов, — ещё −0,50. Отдельная линия — GlobalISel на AArch64 -O0: отставание от FastISel упало с 12,71 до 9,39 процента. Автор оговаривает, что любимую свою правку тут потом откатили. @prog_stuff
277
6
Самый быстрый известный алгоритм печати double безымянный: он живёт в файле yy_double.c внутри JSON-библиотеки yyjson, написан её автором ibireme и почти нигде не описан. Виктор Зверович, автор {fmt}, разобрал, как он устроен и за счёт чего входит в число самых быстрых. Классический Schubfach на каждое число делает два-три 192-битных умножения. Здесь ядро работает на целых фиксированной ширины и обходится одним умножением на заранее вычисленную степень десяти. Дальше рассматриваются четыре кандидата на округление и выбирается кратчайшее корректное представление с округлением к чётному. Отдельно разобран пограничный случай, где алгоритм выбирает между 2e2 и более длинным 19e1, и на первый взгляд это похоже на баг. Автор использует тот же алгоритм в своей библиотеке Żmij. К тексту приложен интерактивный визуализатор на формате E4M3 из 256 кодировок, на котором видно, как работает каждый шаг. @prog_stuff
271
7
Как тестировать сервис, у которого 96 операций в API, больше 500 триллионов объектов и свыше 200 миллионов запросов в секунду? Инженеры Amazon описали свой подход на примере S3: рядом с настоящим сервисом живёт исполняемая эталонная модель, которая хранит состояние и сверяет с ним каждый ответ. Сценарии к модели не пишутся руками и не берутся случайно. Поведение раскладывается на признаки: например, для чтения объекта учитываются 21 параметр запроса, 36 параметров ответа и само содержимое. В одном из экспериментов из 37 признаков получилось 135 категорий поведения и 1025 качественно различных сценариев, которые и генерируются целенаправленно. Сравнение с обычным тестированием на свойствах показательно: там 28 457 запросов дали 9040 уникальных сценариев, остальные 19 417 оказались повторами. У направленной генерации трёхчасовая кампания выполняет около 432 000 запросов. В трёх запусках в конвейере сборки модель поймала 171, 92 и 109 расхождений поведения — среди них десятки настоящих проблем, которые иначе уехали бы дальше. @prog_stuff
278
8
Если хочется разобраться в криптографии руками, а не по формулам, есть Cryptopals — восемь наборов заданий, где вы последовательно ломаете реальные конструкции. Устроено так: предварительных знаний криптографии не требуется, нужен только уверенный навык программирования, а язык любой. Каждое задание решается кодом, а не угадыванием. Первый набор — разминка: hex, Base64, XOR одним байтом, XOR повторяющимся ключом, обнаружение режима ECB. Второй уже интереснее: дополнение по PKCS#7, режим CBC, оракул выбора режима, переворот битов в CBC. Дальше — потоковые шифры, генераторы случайных чисел и повторное использование одноразового значения. Затем атака посредника на обмен ключами Диффи-Хеллмана, подмена параметров группы. Ближе к концу — восстановление сообщений RSA, слабые одноразовые значения в подписях, оракулы дополнения. Почему это не устарело за тринадцать лет: ECB, оракул дополнения, повторно использованный nonce и плохая случайность — это классы ошибок, а не конкретные библиотеки. Оговорка авторов тоже важна: набор учит ломать, но не является руководством по выбору криптографии для продакшена. @prog_stuff
283
9
Обычная модель угроз для защиты от шифровальщиков предполагает, что операционная система на нашей стороне. Группа из Мичиганского университета взяла модель пожёстче: атакующий контролирует ядро, файловую систему, драйверы, гипервизор и даже привилегированного администратора. Защита вынесена ниже всего этого — на уровень блочного устройства. Физический блок нельзя перезаписать до истечения заданного интервала, состояние блоков ведётся в журнале, который можно только дополнять, а каждая операция проверяется перед записью. То есть шифровальщик может записать свои данные, но не может стереть старые. Прототип собран как блочный драйвер для ext4 на Raspberry Pi с обычными диском и твердотельным накопителем. Ядро проверяющей части занимает около 400 строк кода, а свойства «обход невозможен» и «восстановление корректно» доказаны формально в Dafny. Проверили на 18 семействах программ-вымогателей: файловую систему удалось восстановить в каждом случае. Накладные расходы — 0,4 процента по времени и 0,5 процента по пропускной способности накопителя, счётчики занимают около 2 мегабайт на терабайт данных. @prog_stuff
275
10
20 августа на crates.io вышла версия 0.3.10 крейта arrayref. Исходники макросов в ней прежние, в манифесте одно изменение — д
20 августа на crates.io вышла версия 0.3.10 крейта arrayref. Исходники макросов в ней прежние, в манифесте одно изменение — добавлена зависимость proc-macro1 версии 1.0.107. Настоящий крейт называется proc-macro2, а proc-macro1 — типосквот с подделанным полем authors под именем Дэвида Толная; его src/ копирует proc-macro2, поэтому сборка продолжала работать. Вредонос лежит в сборочном скрипте: адрес сервера собирается из base64-фрагментов, бинарник качается по TLS без проверки сертификата и запускается отдельно от сборки. Срабатывает во время компиляции — достаточно просто собрать проект. Отдельный ход: с того же аккаунта отозвали версии с 0.3.5 по 0.3.9. Cargo на отозванную версию предлагает обновиться, и единственной неотозванной оставалась 0.3.10. Rust Security Response Team сообщила, что 0.3.10 была доступна 86 минут: опубликована в 07:15 UTC, удалена в 08:41. Отозванные версии вернули, аккаунт заблокировали. Задеты ещё internment 0.8.7 и append-only-vec 0.1.9. @prog_stuff
281
11
Профилировщик показывает, что горячая функция ждёт память. Дальше начинается гадание: какое именно поле какой структуры не влезает в кэш. Группа из Университета штата Северная Каролина и Google сделала профилировщик, который отвечает на этот вопрос прямо: каждое обращение к памяти связывается с конкретным типом и полем внутри него. Работает поверх штатного perf и отладочной информации, накладных расходов во время работы программы не добавляет, потому что разбор идёт офлайн. Проверяли на ядре Linux 6.17, memcached, Redis, Git, FFmpeg и Binutils. Покрытие типов для обычной сборки Ubuntu — 92,7 процента, циклов ядра — больше 90. У FFmpeg покрытие циклов всего 40 процентов, потому что там много рукописного векторного кода без отладочной информации. Пример находки: в нагрузке MySQL на 256 серверах структура cfs_rq из планировщика занимала 7,58 процента циклов ядра и давала 49,02 процента промахов последнего уровня кэша. Перестановка полей внутри структуры этот вклад заметно снизила. @prog_stuff
257
12
Список, который стоит открывать каждый раз, когда садитесь писать что-то с датами: «Заблуждения программистов о времени» Ноа Сассмана. Тридцать четыре утверждения, каждое из которых кажется очевидно верным и каждое неверно. Во второй части их ещё семьдесят девять. Выборочно: в сутках не всегда 24 часа. Часовой пояс машины не совпадает с поясом пользователя. Часовые пояса меняются политическим решением, а переходы на летнее время не постоянны. Часы клиента и сервера не совпадают. Минута на часах не всегда равна минуте реального времени. Временные метки не обязаны быть уникальными. Время события, время записи в журнал и время получения сообщения — три разных момента. Любимый пример оттуда: виртуальная машина, приостановленная на два часа, после запуска продолжила считать, что всё ещё час дня. Вторая часть добирается до високосных секунд, разницы между настенными и монотонными часами и до того, почему sleep(1000) не значит «ровно секунда». @prog_stuff
267
13
Статический анализатор выдал 147 643 предупреждения о работе с неинициализированной памятью в ядре Linux. Подтвердились и были исправлены 52. Эта цифра — отправная точка работы группы из Калифорнийского университета в Риверсайде, представленной на OSDI в июле. Проблема известна всем, кто пробовал внедрить анализатор в большой проект: покрытие огромное, а доля настоящих находок такая, что список никто не разбирает. Идея авторов: проверять каждое предупреждение отдельно, исполняя подозрительный участок кода по-настоящему. Для этого произвольный набор функций на C и C++ собирается в самостоятельный исполняемый файл без правки исходников, а дальше по нему идёт символьное исполнение. Запускать всё ядро или готовить окружение не нужно. По цифрам: для Linux 6.16.0 удалось собрать 88,9 процента участков, для Android LTS 5.10.240 — 96,2 процента. Разбор одного предупреждения занимал в среднем 0,32 секунды против 5,14 у сравниваемого подхода, а до вердикта доводилось 95,46 процента случаев против 41,29. @prog_stuff
274
14
Телефон переставал играть музыку в Bluetooth-наушниках, как только на компьютере открывалась вкладка AliExpress. Закрыть вкла
Телефон переставал играть музыку в Bluetooth-наушниках, как только на компьютере открывалась вкладка AliExpress. Закрыть вкладку — звук возвращается, замьютить вкладку или всю систему — не помогает. Автор блога laserphile обернул конструктор AudioContext и нашёл два скрытых аудиоконтекста в состоянии running, подключённых к destination, — при том что ни <audio>, ни <video>, ни вызовов play() на странице нет. Создают их collina.js и fireyejs.js из каталога AWSC, антифрод-обвязки Alibaba. Граф в обоих одинаковый: пилообразный осциллятор, AnalyserNode, ScriptProcessorNode, GainNode с нулевым усилением, выход в destination. Слышно ничего, но подключение к destination заставляет браузер обсчитывать граф по-настоящему, и аудиопуть остаётся занятым. Звук здесь одна из мерок отпечатка. Рядом снимаются canvas и toDataURL(), данные WebGL, размеры экрана, hardwareConcurrency, поведение WebRTC, события мыши и скролла, показания акселерометра. @prog_stuff
312
15
Идея, которую в девяностых довели до рабочего состояния, а потом почти все забыли: файловая система, которая одновременно является базой данных. Даниэль Козенца разбирает Be File System — ту, что досталась Haiku от BeOS. У файла там есть не только имя и содержимое, но и типизированные именованные атрибуты: у аудиофайла исполнитель и альбом, у письма отправитель и статус. По выбранным атрибутам строятся индексы, к тому можно писать предикаты, а живые запросы шлют приложению сообщение, когда подходящий файл появился, исчез или изменился. Почтовый клиент, который просто показывает результат запроса к файловой системе, — это оттуда. Автор при этом честно очерчивает границы. Индекс принадлежит конкретному тому: наличие его на загрузочном диске ничего не говорит про соседний. Результат запроса не вечен — файл могут переименовать или удалить. Соединений таблиц, ссылочной целостности и транзакций над несколькими записями тут нет. И главная ловушка: при переименовании атрибуты следуют за файлом, а вот при копировании наружу как повезёт — архиваторы и средства переноса ведут себя по-разному, и на файловой системе без поддержки атрибутов они просто теряются. Байты остались, смысл потерялся. @prog_stuff
290
16
Час, который стоит потратить: доклад Рича Хики «Simple Made Easy» со Strange Loop 2011. Весь доклад держится на разведении двух слов, которые в русском тоже слиплись. Простое — это то, что не переплетено с другими вещами, свойство самой конструкции. Лёгкое — это то, что близко и знакомо лично вам, свойство вашего опыта. Выбирая лёгкое, команда набирает сложность, которую потом невозможно распутать. Хики вводит слово complecting — сплетать вместе то, что могло бы жить раздельно. Изменяемая переменная сплетает значение и время. Наследование сплетает тип и реализацию. Объект сплетает данные и поведение. Всё это удобно писать и тяжело менять через полгода. Отдельный удар по привычным успокоительным: тесты, рефакторинг и система типов повышают безопасность, но не делают дизайн проще. Они ловят ошибки, а не распутывают связи. Практическое, что можно унести на завтра: при проектировании развести вопросы «что», «кто», «как», «когда», «где» и «почему» и следить, чтобы в одном месте не отвечали сразу на несколько. @prog_stuff
307
17
Микаэль Лагерквист собирал корпус из 434 201 судоку для экспериментов с программированием в ограничениях, потом захотел в них поиграть — и сделал игровые версии девяти типов головоломок, где все задачи сгенерированы решателем. Общий приём один: начать с готового решения или картинки, а потом добавлять, двигать и удалять подсказки, пока решение не станет единственным. Для судоку это выглядит так: сгенерировать полную таблицу, убирать подсказки и каждый раз проверять уникальность. Сложность судоку определяется не числом подсказок, а самым слабым набором правил распространения ограничений, которого хватает решателю без перебора вариантов. У других головоломок свои измерения, и метки сравнимы только внутри одного типа. Японские кроссворды описаны регулярным выражением вида Empty* Filled{3} Empty+ Filled{2} Empty*, которое среда сама превращает в конечный автомат. Замкнутая линия в Loopy выражается через готовое ограничение на подциклы, путь в Zip — через ограничение на гамильтонов цикл. И приятная деталь: браузер решателя не запускает вовсе, ему отдают заранее сгенерированные головоломки вместе с решениями. @prog_stuff
310
18
После одной перенастройки контроллера памяти &x != &x: два разных адреса начинают указывать в одну ячейку DRAM, притом что таблицы страниц, TLB и физические адреса, которые видит ядро, никто не трогал. Автор показывает на AMD Family 16h, что финальное преобразование адреса живёт уже за пределами всего, что защищает операционная система. Он проходит цепочку целиком: MMU, EPT и NPT, IOMMU, кэши, когерентная шина, контроллер памяти и только потом чередование по каналам, рангам и банкам. Один переключатель в конфигурации bank-swizzle схлопывает разные адреса в одну физическую координату. Само преобразование не документировано, поэтому автор восстанавливает его как линейное отображение над GF(2) и решает систему линейной алгеброй и Z3. Дальше в README идут доступ к областям PSP, SMM и SMRAM, к C6 save area и микрокоду. Оговорка у автора честная: почти всё проверено на Family 16h, для 17h и новее нужные регистры уже не документированы, а сама документация AMD неполна — порядок XOR-преобразований и стадии MMIO зависят от модели. Переносимость на другие поколения он не обещает. @prog_stuff
327
19
В BGP есть поле ORIGIN: оно говорит, как маршрут попал в протокол, и по стандарту менять его не должен никто, кроме того, кто
В BGP есть поле ORIGIN: оно говорит, как маршрут попал в протокол, и по стандарту менять его не должен никто, кроме того, кто маршрут объявил. Cloudflare проверили, как это соблюдается, и обнаружили, что примерно у 70 процентов наблюдаемых путей значение отличается от исходного. Мотив денежный. При выборе лучшего пути маршрутизатор смотрит на ORIGIN рано, ещё до сравнения других признаков, и предпочитает меньшее значение. Переписав поле в самое приоритетное, транзитный провайдер повышает шанс, что трафик — и оплата за него — пойдёт через него. Эксперимент простой: объявить шесть блоков адресов с разными значениями и посмотреть, что дойдёт до публичных коллекторов. Переписывают немногие, 64 системы из 606 разобранных, но это в основном крупные игроки: шесть из шестнадцати сетей верхнего уровня. Вывод авторов радикальный: осмысленной роли у этого поля в современном интернете не осталось. @prog_stuff
325
20
На iOS браузеры за пределами ЕС обязаны работать на WebKit, а прокси-браузеры вроде Tor-клиентов настраивают прокси через WKWebsiteDataStore.proxyConfigurations: весь трафик страницы должен уходить через прокси. Исследователи Mysk нашли три функции WebKit, которые эту настройку обходят и ходят в сеть напрямую с устройства. <link rel="dns-prefetch"> резолвит имя через системный DNS, а не через прокси: сайт вставляет уникальное имя на посетителя и смотрит, с какого резолвера прилетает запрос. WebAuthn Related Origin Requests заставляет системный сервис учётных данных скачать файл проверки напрямую, раскрывая реальный IP. WebTransport поднимает прямое HTTP/3-соединение мимо прокси. Функции появились в iOS 26.0, 18.0 и 26.4 соответственно. Всё это происходит вне обычного цикла загрузки страницы, поэтому утечки задевают и iCloud Private Relay; VPN не затронуты, они тянут трафик на уровне системы. Началось с одного бага от пользователя, у которого DNS утекал только на некоторых сайтах: без тега prefetch запроса просто не было. Авторы делают собственный браузер Psylo: в 1.3.1 prefetch блокируется, а WebTransport и WebAuthn выключены по умолчанию и включаются отдельной настройкой на сайт. PoC лежит на leaks.psylo.app. @prog_stuff
333