Перейти к содержимому

NUL-байт ломает XML/XDTO и запись в ЖР — чистить вход

Директивный

#кодировки#xdto#обработка-ошибок

Текст из внешнего источника (HTTP-тело, файл, обмен), который пишется в ЖурналРегистрации или сериализуется в XML/XDTO, предварительно очищать от Символ(0). Наличие NUL-байта ломает запись/просмотр события и разбор XML.

Откуда NUL берётся в «тексте»:

  • тело пришло в UTF-16LE, а прочитано как UTF-8 — NUL между каждым ASCII-символом (самый частый случай);
  • в строку попал кусок бинарных данных (вложение, повреждённый файл, обрезанный буфер);
  • внешняя система прислала NUL намеренно или по своей ошибке — на входе это неотличимо, чистить надо всегда.
  • При открытии события в ЖР: «Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа» с упоминанием XDTO и «недопустимый символ в позиции N».
  • Веб-клиент: фатальная ошибка Char 0x0 out of allowed range при работе с файлами/отчётами — в том числе как следствие частично заблокированного потока (см. WAF и служебные пути).
  • FillJournalList падает с XDTO-ошибкой.

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

NUL-байты часто появляются потому, что тело пришло в UTF-16LE (NUL между ASCII-символами) — сначала корректно определите кодировку, затем вычистите остаточные NUL.

HTTP-сервис-провайдер второго фактора аутентификации логировал тело входящего запроса «как есть». Платформа прислала шаблон 2FA в UTF-16LE — в строке оказался NUL после каждого ASCII-символа, и сломалась не обработка запроса, а диагностика: событие ЖР с этим телом не открывалось («Значение недопустимого типа», XDTO, «недопустимый символ в позиции N»), а просмотр журнала падал на FillJournalList. То есть именно в момент, когда лог был нужнее всего, он перестал читаться. Порядок починки — по этому стандарту: сначала корректное чтение кодировки тела, затем очистка от NUL перед любой записью в ЖР.

Исключений нет: любой внешний текст перед ЖР/XDTO проходит очистку от Символ(0).