From f83e27260d4cf2fce58e3022012300d9b38824ba Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 26 Oct 2026 17:07:18 +0100 Subject: [PATCH] Record rebased DM verification and UTF-8 name truncation defect --- doc/dm_arch.md | 5 ++++ doc/dm_audit_findings.txt | 61 +++++++++++++++++++++++++++++++++++++++ doc/tasks.md | 10 +++++++ src/dm/dm_core.h | 4 ++- src/dm/dm_media.h | 6 +++- 5 files changed, 84 insertions(+), 2 deletions(-) diff --git a/doc/dm_arch.md b/doc/dm_arch.md index d8294474..8f4cac75 100644 --- a/doc/dm_arch.md +++ b/doc/dm_arch.md @@ -57,6 +57,11 @@ AES-256-CCM: nonce 13 байт, tag 16 байт. Максимальная пор Длительность ограничена 24 часами, размеры — 16384. Метаданные проверяются до локального commit и до подтверждения получателем; S/M видят только ciphertext. +**Известный дефект снимка бесед (26.10.2026):** фиксированный `peer_name[64]` +усекает длинное корректное UTF-8-имя по байтам. Для 32 букв «Я» сохраняется +неполная последовательность без последнего байта, и JSON списка бесед с кодом успеха0 +становится некорректным UTF-8. Подробности и план: [dm_audit_findings.txt](dm_audit_findings.txt), раздел8. + Медиа ciphertext — последовательность порций с отдельным tag каждой порции. Последняя порция короче; пустой файл содержит один tag. Размер plaintext и SHA256 ciphertext должны входить в подписанный manifest. Потоковая расшифровка проверяет все diff --git a/doc/dm_audit_findings.txt b/doc/dm_audit_findings.txt index 4caa7720..05f117d3 100644 --- a/doc/dm_audit_findings.txt +++ b/doc/dm_audit_findings.txt @@ -264,3 +264,64 @@ media-теста/native/sanitizer/контролей прочитаны;ожид временная make-цель исправлена до контрольных прогонов. Основная сборка/код от этого не менялись. Документация обновлена,задача quota-admission закрыта. Остальные отметки аудита DM остаются частичными;GUI/Android/Windows/FreeBSD не запускались. Коммит/push не выполнялись. + +7. Commit/rebase/push по запросу пользователя — 26.10.2026 + +Все накопленные изменения DM сохранены в2ae1990d. Fetch обнаружил8 новых коммитов +origin/master поверх03b05094:изменения headless PCM,документации звонков и их проверок. +Rebase на03be46c3 завершён с единственным конфликтом doc/tasks.md:сохранены обе +полные группы задач. tests/Makefile.am объединился автоматически,цели test_dm_load, +quota wrappers test_dm_media и upstream test_call_headless_queue присутствуют. +DM .c/.h и обе новые/расширенные регрессии побайтно сохранены относительно исходного коммита. + +После rebase коммит стал b6588d059455ed430c902a325af7d010f15f3475. +Нативная сборка PASS;новый полный check.sh204/204 PASS,0 failed/0 skipped, +proxy9/9,burst1/1,load8/8 PASS,134217728 байт,exit0,175с. Включён новый upstream +test_call_headless_queue (11/11) и все DM-регрессии. Сеть — отдельный IPv6 namespace. +Push origin master:03be46c3..b6588d05 PASS,без force. git ls-remote подтвердил hash, +HEAD==origin/master,рабочее дерево после push было чистым. +Логи:/tmp/dm-audit-rebase-build.log,/tmp/dm-audit-rebase-full-check.log, +/tmp/dm-audit-rebase-netns.log. Санитайзеры после rebase заново не запускались; +исходные DM-файлы по сравнению с прошедшим sanitizer-профилем не менялись. + +8. Продолжение: UTF-8 имя повреждается при построении беседы + +Продолжены сверка core/history,передачи поколения и путей из attachment_send, +участков headless/GUI/JNI вызывающих функций. Это чтение кода,не аппаратная проверка UI. +Уточнён dm_send_file:0 означает вызов submit,который вправе синхронно вызвать callback +ошибки;результат подготовки сообщается событием. Это исправление описания возврата. + +Новый подтверждённый дефект:dm_conv.peer_name[64],snprintf в dm_start/dm_conv_load +режут имя по63байтам,без проверки границы UTF-8. json_escape передаёт получившиеся +байты в JSON без проверки/исправления. Корректное входное имя тем самым повреждается +в SQLite,а dm_list_conversations_json возвращает0 с некорректным UTF-8 JSON. +dm_start_req допускает до127байт имени;отсутствует предусловие ASCII/<=63байт. + +Стенд:/tmp/dm-utf8-audit.c/.mk. Настоящие core/chat_service/SQLite/X25519, +отдельные ключи для трёх собеседников,новая БД/tmp;публичные dm_start/list API. +Валидные входы:ASCII63байта;31×«Я»=62байта;32×«Я»=64байта. +Контроли ASCII63/UTF8_62 дают корректный UTF-8 JSON. UTF8_64 сохраняется как63байта, +последний байт0xd0 без продолжения;start=0,list=0. Строгий Python decode JSON +даёт invalid continuation byte на позиции537;проверка exit2. SQL-readonly-снимок +подтверждает тот же обрыв в сохранённом peer_name,tail_hex=afd0afd0afd0afd0. +Tracked allocations0->0;собственно C-стенд exit0,отказ обнаруживает независимый валидатор. +Сам runtime-лог тоже содержит этот некорректный байт:валидатор читает диагностический +лог с replacement только для поиска ASCII-путей,но JSON и SQL BLOB проверяет строго. + +Причина однозначна по точным входным/сохранённым длинам и байтам;это не ошибка JSON +парсера,шифрования или вывода терминала. Повторная загрузка имени через dm_conv_load +имеет то же побайтовое усечение;этот путь в новом стенде отдельно не запускался. + +Простой план:определить единое ограничение имени и копировать только целые UTF-8 +code points. Проверять входы и уже сохранённые некорректные строки с диагностикой; +увеличение массива само по себе не решает обрыв на новой границе. +Постоянные проверки:ASCII и2/3/4-байтовые символы до/на/за границей,SQL round-trip, +повторная загрузка и строгая декодируемость JSON. До выбора обработки уже повреждённых +имён (безопасное усечение/отказ) рабочая реализация не менялась. + +Логи:/tmp/dm-utf8-audit-build.log,/tmp/dm-utf8-audit-runtime.log, +/tmp/dm-utf8-audit-validation.log;валидатор:/tmp/dm-utf8-audit-validate.py. +По AGENTS.md:10 дальнейший аудит остановлен,задача открыта в doc/tasks.md. +В продолжении только комментарии/документы,все текущие частичные отметки сохранены. +Предыдущий check204 проверял объединённые исправления,а не обработку нового имени; +новые sanitizer/GUI/Android/Windows/FreeBSD проверки не запускались. diff --git a/doc/tasks.md b/doc/tasks.md index f5b1d176..7de06435 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -4,6 +4,16 @@ ## Текущие задачи +[ ] **DM: сохранять границы UTF-8 при усечении имени собеседника** — подтверждено 26.10.2026. + dm_start и dm_conv_load копируют имя через snprintf в peer_name[64],json_escape не проверяет UTF-8. + Валидные64байта (32×«Я») сохраняются как63байта с оборванным0xd0;start/list возвращают0, + строгий decode UTF-8 JSON даёт invalid continuation byte. ASCII63 и UTF8_62 — PASS;allocations0->0. + Нужен единый контракт UTF-8 копирования при сохранении/загрузке:усечение только целых code points, + обработка уже некорректных сохранённых имён с диагностикой,границы двух/трёх/четырёхбайтовых символов. + Увеличение буфера само по себе проблему не устраняет. Стенд /tmp/dm-utf8-audit.c/.mk, + логи /tmp/dm-utf8-audit-{build,runtime,validation}.log. Аудит остановлен по AGENTS.md:10. + Подробности: [dm_audit_findings.txt](dm_audit_findings.txt),раздел8. Production/тесты в этом этапе не менялись. + [ ] **Android call mute: передавать настоящий PCM и флаг mute через JNI до core** — подтверждено 26.10.2026. CallAudioEngine.captureLoop заменяет микрофон тишиной до nativeCallAudioFeed; bridge вызывает feed_pcm. Включённый AEC после этого снова создаёт ненулевой сигнал перед Opus. Стенд с настоящими bridge/Opus/AEC, diff --git a/src/dm/dm_core.h b/src/dm/dm_core.h index d56e3e49..5845d91d 100644 --- a/src/dm/dm_core.h +++ b/src/dm/dm_core.h @@ -103,7 +103,9 @@ void dm_delete_trampoline(void* arg); void dm_cancel_pending_history(struct UTUN_INSTANCE* inst, const char* conv); /* До 200 видимых бесед по last_ts DESC: [{conv_id,peer_node_id,peer_name,last_ts,out_seq,in_seq,generation}]. - * buf вмещает JSON и NUL; 0 и *out_len без NUL при успехе, -1 при ошибке. Все вызовы в uasync. */ + * buf вмещает JSON и NUL; 0 и *out_len без NUL при успехе, -1 при ошибке. Все вызовы в uasync. + * Известный дефект: имя может быть обрезано внутри UTF-8 в dm_start/load, и результат с кодом0 будет + * некорректным UTF-8 JSON. См. doc/dm_audit_findings.txt, раздел8. */ int dm_list_conversations_json(struct UTUN_INSTANCE* inst, char* buf, size_t buf_size, size_t* out_len); /* Сообщения беседы в JSON: расшифрованное содержимое, статусы доставки и медиа. diff --git a/src/dm/dm_media.h b/src/dm/dm_media.h index 30b2a7de..5b7e02f6 100644 --- a/src/dm/dm_media.h +++ b/src/dm/dm_media.h @@ -33,7 +33,11 @@ int dm_media_init(struct UTUN_INSTANCE* inst); void dm_media_quiesce(struct UTUN_INSTANCE* inst); void dm_media_destroy(struct UTUN_INSTANCE* inst); -/* Подготовить копию и enqueue file-сообщение асинхронно. 0=задача принята. */ +/* Передать подготовку копии и enqueue file-сообщения в media_async. + * Строки conv/path и info копируются при вызове; сам файл должен быть доступен worker до завершения. + * 0=submit вызван, -1=отказ до submit. Submit может синхронно завершиться ошибкой через callback; + * готовность/ошибка подготовки сообщается CHAT_EVT_ATTACHMENT_PREPARATION, включая до возврата0. + * remove_source=1 передаёт worker собственный временный файл приложения для удаления; при -1 его убирает caller. */ int dm_send_file(struct UTUN_INSTANCE* inst, const char* conv, const char* path, const struct attachment_info* info, int remove_source); struct dm_file_req {