From 0d616ce1e7a155bb4effd8bc7e783010ccd4aadf Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 24 Oct 2026 15:48:05 +0200 Subject: [PATCH] docs(media): record unchecked SQLite announcements and fix plan --- doc/media_async_audit_findings.txt | 71 +++++++++++++++++++++++++++++- doc/tasks.md | 13 ++++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/doc/media_async_audit_findings.txt b/doc/media_async_audit_findings.txt index 18ccb342..41a15f55 100644 --- a/doc/media_async_audit_findings.txt +++ b/doc/media_async_audit_findings.txt @@ -1,6 +1,6 @@ Аудит media_async / media_delivery — 2026-10-24 -Статус: encrypted_file и отдельный дефект границы voice_file исправлены. -Полный аудит двух каталогов ещё не завершён. Граница voice_file и результаты исправления — в конце. +Статус: encrypted_file и граница voice_file исправлены; подтверждён отдельный дефект переанонса записей SQLite. +Полный аудит двух каталогов ещё не завершён. Последнее продолжение и проект исправления — в конце. Ниже сохранены исходное воспроизведение, согласованный проект и результаты исправления encrypted_file. Подтверждённый дефект: исходник уничтожается через другое имя того же файла @@ -296,3 +296,70 @@ attachment_send.c вызывает voice_file_encode в worker, а attachment_va выше не относятся к этому изменению. Windows/FreeBSD не проверялись. voice_file.h и attachment.h сохраняют [~]: завершение этого фикса не закрывает оставшуюся сверку контрактов всего аудита. Повторная проверка media_delivery ещё не завершена. + +Продолжение аудита — 2026-10-24: переанонс записей SQLite + +Полностью прочитаны media_index.c/h, media_download.c/h, media_delivery.c/h, +file_transfer.c/h, media_delivery_proto.h и sync.md. Повторно сверены media_crypto.c/h. +В media_crypto.h уточнены native байты nonce, границы CCM/буферов, пустой поток, +момент выдачи размеров/хеша и отсутствие close/fsync/rename; неверный аргумент не обнуляет выходы. +В file_transfer.h уточнены lookup/авторизация, 16 операций, размер1..INT64_MAX, +усечение своего временного назначения даже при отказе запуска, таймаут и отмена/владение callback. +Изменения только описаний сохранены коммитом5dbca4a2. + +Подтверждённый дефект + +media_delivery_announce_local_blocks (media_delivery.c:1604) читает media_id/block_id +через sqlite3_column_blob, но проверяет только ненулевой указатель. Затем +media_delivery_send_have_block копирует по16 байт в пакет и подписывает объявление. +media_files имеет BLOB NOT NULL без CHECK длины: такие строки допустимы текущей схемой. +Обычные media_index writers пишут правильные длины; опыт моделирует повреждённые +локальные данные, а не доказанный путь внесения повреждения удалённым участником. + +Настоящие SQLite, схема, обработчик, выбор группы/суперузла и Ed25519; перехвачена +только транспортная отправка в существующем tests/media_delivery_fixture.h: +- Контрольные UUID16/16, chunk0, chat_id111: один корректный HAVE_BLOCK. +- media_id длиной1 байт: один HAVE_BLOCK с16-байтным media_id, из них15 байт вне BLOB. + В журнале вместо ожидаемого единственного7a видны посторонние ненулевые байты памяти. +- block_id длиной1 байт: аналогичное чтение15 лишних байт в сетевой block_id. +- media_id или block_id длиной17 байт: отправка с молчаливым усечением до16. +- chunk=-1: wire_chunk=4294967295; chunk=4294967296: wire_chunk=0. + Причина — sqlite3_column_int с последующим приведением к uint32_t без диапазона. +- chat_id111junk: strtoull без endptr принимает префикс111 и направляет объявление в группу111. +- Итого8 случаев,7 повреждённых строк из7 отправлены; invalid_records_sent=7, confirmed=1. + Ошибки соответствующих полей в модуле не логируются. Пакеты сохранены только стендом, + реальные удалённые узлы в опыте не участвовали. Ошибка ASAN или падение не воспроизводились. + +Артефакты: /tmp/media-announcement-audit.c, /tmp/media-announcement-audit.mk, +/tmp/media-announcement-audit-build.log, /tmp/media-announcement-audit.log. +Сборка через tests/Makefile с настоящими src/libutun.a/libuasync.a и штатными флагами; +проектные .c для диагностики не менялись. Очистка собственного стенда исправлена и повторно проверена. +Отдельно по коду видно: результаты bind/завершающего step/finalize игнорируются; +SQL-ошибку окончания обхода нельзя выдавать как обычное «done». Инъекция SQL-ошибок здесь не выполнялась. + +Проект простого исправления + +1. Проверять строку на границе чтения SQLite до доступа как к фиксированным структурам: + media_id/block_id имеют тип BLOB и ровно16 байт; проверить полученные указатели. + Скопировать прошедшие проверку UUID в локальные массивы до вложенных SQL/отправок. +2. chunk читать как int64: тип INTEGER, 0..UINT32_MAX, только затем cast. + chat_id — TEXT, длина1..20 без embedded NUL, каноническое ненулевое uint64 decimal. + Полный разбор должен отвергать суффиксы, знаки, пробелы, leading zero и переполнение; + строка канала должна сохранять свой смысл при переводе в router group_id. +3. Плохую строку пропускать с WARN, указав rowid/типы/длины/некорректное поле, + без чтения за BLOB и без анонса. Корректные соседние строки продолжать обрабатывать. + Никакого общего выделяемого снимка или отката уже отправленных корректных анонсов не требуется. +4. Проверять bind, terminal step и finalize; SQL-ошибки логировать с фазой/кодами + и количеством обработанных строк. Не превращать их в обычный успешный финальный лог. + Сохранить существующий void API, поштучные анонсы и wire-формат. +5. Регрессии в штатной media-цели: valid row, длины UUID0/1/15/16/17 и неверные SQL-типы, + chunk=-1/0/UINT32_MAX/UINT32_MAX+1, неверные/граничные chat_id, embedded NUL; + смесь корректных/плохих записей и ошибки SQL. Перехват HAVE_BLOCK обязан доказать, + что наружу ушли только исходные16 байт проверенных UUID и правильный номер группы/блока. + +Аудит остановлен по AGENTS.md:10 после подтверждения дефекта и подготовки проекта исправления. +Новые полные build/check/sanitizer-прогоны не запускались: изменения в репозитории только документальные. +media_crypto.h и file_transfer.h можно отметить [V]; media_delivery.h/proto.h остаются [~]: +нужно исправление этого пути и завершение сверки описаний. Остальные прежние отметки не закрывают +весь аудит. Остались контракты attachment/attachment_send/voice, связанные encrypted/lifecycle документы +и устаревший _desc.txt (RTT-подбор, direct-only репликация и её интервалы расходятся с текущим кодом). diff --git a/doc/tasks.md b/doc/tasks.md index a64ed906..ec7f3860 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -4,6 +4,19 @@ ## Текущие задачи +[ ] **media_delivery: проверять записи SQLite перед переанонсом локальных блоков** — подтверждено 24.10.2026. + announce_local_blocks не проверяет длины media_id/block_id, диапазон chunk и полный chat_id. + Реальный обработчик отправил все7 повреждённых записей: UUID длиной1/17 байт, chunk=-1/2^32, chat_id=111junk. + При UUID длиной1 байт остальные15 байт сетевого поля взяты за границей BLOB; + chunk=-1 превращается в4294967295, 2^32 — в0, 111junk — в группу111. + Стенд использует настоящие SQLite/Ed25519; отправка перехвачена, пакеты в реальную сеть не уходят. + Воспроизведение: /tmp/media-announcement-audit.c и .mk; лог: /tmp/media-announcement-audit.log. + План: проверять типы/точные длины UUID, chunk через int64 и канонический ненулевой десятичный chat_id + до копирования/кастов/отправки. Плохие строки логировать и пропускать; проверять bind/step/finalize. + Сохранить текущий void API, поштучные анонсы и формат wire; общий снимок всех файлов не нужен. + Архитектура, границы воспроизведения и регрессии: [media_async_audit_findings.txt](media_async_audit_findings.txt). + Рабочий код не изменён: остановлено по AGENTS.md:10. Сверка описаний двух каталогов ещё не завершена. + [+] **media_async voice_file: согласовать верхнюю границу длительности с метаданными** — исправлено 24.10.2026. Прежняя проверка samples/channels/rate >86400 пропускала полные кадры 24ч+20..980мс, хотя attachment_validate отклоняет duration_ms >86400000. В штатном pipeline это означает