From ecba318decabdb232f2bd0eaeba88161623f8743 Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 22 Oct 2026 19:48:47 +0200 Subject: [PATCH] Record validated media block ownership and relay fixes --- doc/tasks.md | 19 +++++++++++++++---- tests/test_media_blocks.c | 22 +++++++++++----------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/doc/tasks.md b/doc/tasks.md index 26bba727..267d4785 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -101,23 +101,28 @@ Неиспользуемые chunk/rtt удалены из нового формата QUERY_RESP. Блок однозначно задаётся block_id, а его номер загрузчик берёт из сохранённых метаданных; позиция в выборочной пачке не считается номером блока. -[ ] **media_delivery CHUNK: прогресс только после проверенного приёма и записи** — воспроизведено 22.10.2026: +[+] **media_delivery CHUNK: прогресс только после проверенного приёма и записи** — исправлено 22.10.2026: Реальные router callbacks/SQLite, корректные подпись блока и ключ автора. CHUNK с data_len=1 без payload оставляет файл пустым, но устанавливает bytes_received=1, RECV и обновляет last_progress_tb. То же при внедрённом fwrite=0/ENOSPC. Текущий unit-тест допускает 456 байт при expected_size=100. Проверять полный payload, геометрию/непрерывность, текущего держателя и попытку до файловых операций; не считать дубли и неудачную запись прогрессом. Нужна привязка пакетов к отдельной попытке передачи блока. Стенд /tmp/media-block-audit.c; логи /tmp/media-block-audit-truncated.log, /tmp/media-block-audit-write.log. + Реализованы строгие размеры/непрерывность, tuple группы/держателя/блока/UUID и отдельный temp каждой попытки. + Прогресс публикуется после проверенного close. Регрессии: tests/test_media_blocks.c, включая реальные I/O-сбои. -[ ] **media_delivery DONE: проверка ключа и конечный результат ошибки хеша** — воспроизведено 22.10.2026: +[+] **media_delivery DONE: проверка ключа и конечный результат ошибки хеша** — исправлено 22.10.2026: Для настоящей Ed25519 пары с pubkey[0]=0 корректно подписанный блок отвергается: наличие ключа определяется первым байтом. При отсутствии ключа проверка заменяется сравнением wire block_sig с метаданными. Отдельно: при верной подписи блока и несовпадающем хеше файла state=DONE, validated=0/1, active=1; три проверки watchdog возвращают 0, done не вызывается. Итоговая ошибка должна завершать загрузку, а публикация назначения и регистрация допустимы только после проверенных чтения/записи/close/SHA256. - Логи /tmp/media-block-audit-keyzero.log, /tmp/media-block-audit-hash.log; реализация не менялась. + Обязателен ключ ровно 32 байта; проверяется подпись метаданных по фактическим байтам и ожидаемый размер. + Сборка идёт в собственный temp, SHA-256 проверяется всегда, затем publish и регистрация SQLite. + Ошибка до publish сохраняет старое назначение; ошибка SQLite сохраняет подготовленный опубликованный файл. + Регрессии с настоящим pubkey[0]=00, неверной подписью/хешем, сбоями I/O/rename/SQLite: tests/test_media_blocks.c. -[ ] **media_delivery progress_cb: отмена освобождает dl внутри обработчика DONE** — подтверждено ASAN 22.10.2026: +[+] **media_delivery progress_cb: отмена освобождает dl внутри обработчика DONE** — исправлено 22.10.2026: progress_cb вызывает media_download_cancel, md_dl_finish освобождает dl; media_download_handle_done затем вызывает md_dl_send_have_block с освобождённым указателем. ASAN heap-use-after-free, чтение 8 байт. Обработчик явно удерживает контекст. Terminal снимает загрузку с индекса и отменяет её timers/CM/waiters; @@ -126,6 +131,12 @@ в конец функции/отложенный финализатор не заменяет владение. Relay-получатели отдельно удерживают файл блока. Проверить также отмену с повторным start того же media_id, отмену на последнем progress и поздние пакеты. Лог /tmp/media-block-audit-cancel-asan.log; стенд вне репозитория /tmp/media-block-audit.c. + Реализовано явное удержание контекста обработчиком; отдельные ссылки producer/выдач удерживают файл блока. + Единый TX pump готовых/растущих источников соблюдает backpressure для DATA и DONE; remote CANCEL привязан к UUID. + Проверены отмена/повторный start из последнего progress и старые relay-читатели при успехе/отмене новой загрузки. + Полный ./check.sh: 179/179, proxy/burst/load PASS (/tmp/media-block-full-check-final.log). + Десять целевых наборов ASAN+UBSan с detect_leaks=1: PASS (/tmp/media-block-asan-test_*.log). + Windows runtime/сборка не проверялись. Синхронные проверка и сборка блоков остаются в uasync. [+] **test_stream_service: убрать зависимость bootstrap-проверки от гонки TCP-handshake** — исправлено 22.10.2026: Падение на строке 409: REINIT=0 при probes=1/subflows=1/failures=0 и доставленной первой пачке. diff --git a/tests/test_media_blocks.c b/tests/test_media_blocks.c index 70fa0209..3939120c 100644 --- a/tests/test_media_blocks.c +++ b/tests/test_media_blocks.c @@ -130,17 +130,17 @@ static void test_identity_and_bounds(void) { struct packet bad = done; bad.len = length; unchanged(f.client, &bad); } for (int variant = 0; variant < 6; variant++) { - struct packet bad = done; - struct media_pkt_block_done* d = (struct media_pkt_block_done*)bad.data; - switch (variant) { - case 0: bad.group++; break; - case 1: bad.from++; break; - case 2: d->media_id[0]++; break; - case 3: d->block_id[0]++; break; - case 4: d->transfer_id[0]++; break; - case 5: d->chunk++; break; - } - unchanged(f.client, &bad); + struct packet bad = done; + struct media_pkt_block_done* d = (struct media_pkt_block_done*)bad.data; + switch (variant) { + case 0: bad.group++; break; + case 1: bad.from++; break; + case 2: d->media_id[0]++; break; + case 3: d->block_id[0]++; break; + case 4: d->transfer_id[0]++; break; + case 5: d->chunk++; break; + } + unchanged(f.client, &bad); } struct packet stale = {.from = good.from, .group = GROUP, .len = sizeof(struct media_pkt_block_overloaded)}; struct media_pkt_block_overloaded* ov = (struct media_pkt_block_overloaded*)stale.data;