Пути к коду в кодировке UTF-7 устарели

Кодировка UTF-7 больше не используется широко в приложениях, и многие спецификации теперь запрещают использовать ее при обмене. Кроме того, иногда она служит вектором атаки в приложениях, которые не предусматривают получение данных в этой кодировке. Корпорация Майкрософт предостерегает от использования класса System.Text.UTF7Encoding, так как он не выполняет обнаружение ошибок.

Таким образом, свойство Encoding.UTF7 и конструкторы UTF7Encoding теперь также считаются устаревшими. Кроме того, методы Encoding.GetEncoding и Encoding.GetEncodings больше не позволяют определять UTF-7.

Описание изменения

Ранее экземпляр кодировки UTF-7 можно было создать с помощью API Encoding.GetEncoding. Например:

Encoding enc1 = Encoding.GetEncoding("utf-7"); // By name.
Encoding enc2 = Encoding.GetEncoding(65000); // By code page.

Кроме того, экземпляр, представляющий кодировку UTF-7, перечислялся методом Encoding.GetEncodings(), который перечисляет все зарегистрированные в системе экземпляры Encoding.

Начиная с .NET 5, свойство Encoding.UTF7 и конструкторы UTF7Encoding являются устаревшими и выдают предупреждение SYSLIB0001. Но чтобы уменьшить число предупреждений, получаемых вызывающими объектами при использовании класса UTF7Encoding, сам тип UTF7Encoding не помечен как устаревший.

// The next line generates warning SYSLIB0001.
UTF7Encoding enc = new UTF7Encoding();
// The next line does not generate a warning.
byte[] bytes = enc.GetBytes("Hello world!");

Кроме того, методы Encoding.GetEncoding интерпретируют имя кодировки utf-7 и кодовую страницу 65000 как unknown. Получение значения unknown для кодировки вызывает исключение ArgumentException.

// Throws ArgumentException, same as calling Encoding.GetEncoding("unknown").
Encoding enc = Encoding.GetEncoding("utf-7");

Наконец, метод Encoding.GetEncodings() не включает кодировку UTF-7 в возвращаемый массив EncodingInfo. Кодировка исключается, так как нельзя создать ее экземпляр.

foreach (EncodingInfo encInfo in Encoding.GetEncodings())
{
    // The next line would throw if GetEncodings included UTF-7.
    Encoding enc = Encoding.GetEncoding(encInfo.Name);
}

Причина изменения

Многие приложения вызывают метод Encoding.GetEncoding("encoding-name") с именем кодировки, полученным от ненадежного источника. Например, веб-клиент или сервер может взять фрагмент charset из заголовка Content-Type и передать его значение непосредственно в Encoding.GetEncoding без проверки. Это позволяет вредоносной конечной точке указать Content-Type: ...; charset=utf-7, что может привести к сбою принимающего приложения.

Кроме того, отключение путей к коду в UTF-7 позволяет оптимизировать работу компиляторов, например используемых в Blazor. При этом такие пути к коду полностью удаляются из полученного приложения. В результате скомпилированные приложения работают более эффективно и занимают меньше места на диске.

Представленные версии

5,0

В большинстве случаев никаких дополнительных действий от вас не требуется. Но если в приложении ранее были активированы пути к коду в UTF-7, воспользуйтесь приведенными ниже рекомендациями.

  • Если приложение вызывает метод Encoding.GetEncoding с неизвестными именами кодировки, полученными от ненадежного источника:

    Вместо этого рекомендуется выполнять проверку имен кодировки по списку разрешенных. Этот настраиваемый список разрешенных кодировок должен по меньшей мере содержать стандартную отраслевую кодировку UTF-8. В зависимости от потребностей ваших клиентов и нормативных требований вам может также понадобится разрешить кодировки для определенных регионов, например GB18030.

    Если вы не создадите список разрешенных кодировок, метод Encoding.GetEncoding будет возвращать все значения Encoding, которые встроены в систему или зарегистрированы с помощью настраиваемого класса EncodingProvider. Проверьте требования службы, чтобы убедиться, что такое поведение допустимо. По умолчанию кодировка UTF-7 остается отключенной, если только приложение не включит параметр совместимости, упомянутый далее в этой статье.

  • Если вы используете Encoding.UTF7 или UTF7Encoding в своем формате протокола или файла:

    Перейдите на использование Encoding.UTF8 или UTF8Encoding. Кодировка UTF-8 является отраслевым стандартом, поддерживающим различные языки, операционные системы и среды выполнения. Использование UTF-8 упрощает дальнейшее обслуживание кода и улучшает его совместимость с остальной экосистемой.

  • Если вы сравниваете экземпляр Encoding со свойством Encoding.UTF7:

    Вместо этого рекомендуется выполнять проверку по кодовой странице UTF-7 — 65000. Сравнение с кодовой страницей позволяет избежать предупреждения, а также обрабатывать некоторые пограничные случаи, например, когда вызывается new UTF7Encoding() или создается подкласс типа.

    void DoSomething(Encoding enc)
    {
        // Don't perform the check this way.
        // It produces a warning and misses some edge cases.
        if (enc == Encoding.UTF7)
        {
            // Encoding is UTF-7.
        }
    
        // Instead, perform the check this way.
        if (enc != null && enc.CodePage == 65000)
        {
            // Encoding is UTF-7.
        }
    }
    
  • Если вам необходимо использовать Encoding.UTF7 или UTF7Encoding:

    Вы можете отключить предупреждение SYSLIB0001 в коде или в файле .csproj проекта.

    #pragma warning disable SYSLIB0001 // Disable the warning.
    Encoding enc = Encoding.UTF7;
    #pragma warning restore SYSLIB0001 // Re-enable the warning.
    
    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
       <TargetFramework>net5.0</TargetFramework>
       <!-- NoWarn below suppresses SYSLIB0001 project-wide -->
       <NoWarn>$(NoWarn);SYSLIB0001</NoWarn>
      </PropertyGroup>
    </Project>
    

    Примечание.

    При подавлении SYSLIB0001 отключаются только предупреждения о том, что Encoding.UTF7 и UTF7Encoding являются устаревшими. Это не отключает другие предупреждения и не меняет поведение API-интерфейсов, например Encoding.GetEncoding.

  • Если требуется поддержка Encoding.GetEncoding("utf-7", ...):

    Вы можете повторно включить поддержку этой кодировки с помощью переключателя совместимости. Этот переключатель совместимости можно указать в файле .csproj приложения или файле конфигурации среды выполнения, как показано в следующих примерах.

    В файле .csproj приложения:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
       <TargetFramework>net5.0</TargetFramework>
       <!-- Re-enable support for UTF-7 -->
       <EnableUnsafeUTF7Encoding>true</EnableUnsafeUTF7Encoding>
      </PropertyGroup>
    </Project>
    

    В файле runtimeconfig.template.json:

    {
      "configProperties": {
        "System.Text.Encoding.EnableUnsafeUTF7Encoding": true
      }
    }
    

    Совет

    При повторном включении поддержки UTF-7 следует выполнить проверку безопасности кода, который вызывает Encoding.GetEncoding.

Затронутые API