Мы решили в меру своих сил регулярно искать и устранять уязвимости и баги в различных проектах. Можно назвать это помощью open-source проектам. Можно — разновидностью рекламы или тестированием анализатора. Еще вариант — очередной способ привлечения внимания к вопросам качества и надёжности кода. На самом деле, не важно название, просто нам нравится это делать. Назовём это необычным хобби. Давайте посмотрим, что интересного было обнаружено в коде различных проектов на этой неделе. Мы нашли время сделать исправления и предлагаем вам ознакомиться с ними.

Для тех, кто ещё не знаком с инструментом PVS-Studio


PVS-Studio — это инструмент, который выявляет в коде многие разновидности ошибок и уязвимостей. PVS-Studio выполняет статический анализ кода и рекомендует программисту обратить внимание на участки программы, в которых с большой вероятностью содержатся ошибки. Наилучший эффект достигается тогда, когда статический анализ выполняется регулярно. Идеологически предупреждения анализатора подобны предупреждениям компилятора. Но в отличии от компиляторов, PVS-Studio выполняет более глубокий и разносторонний анализ кода. Это позволяет ему находить ошибки в том числе и в компиляторах: GCC; LLVM 1, 2, 3; Roslyn.

Поддерживается анализ кода на языках C, C++ и C#. Анализатор работает под управлением Windows и Linux. В Windows анализатор может интегрироваться как плагин в Visual Studio.

Для дальнейшего знакомства с анализатором, предлагаем изучить следующие материалы:

  • Подробная презентация на сайте SlideShare. В формате видео она доступна на YouTube (47 минут).
  • Статьи о проверенных открытых проектах.

Уязвимости


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

1. CoreFX. CWE-476 (NULL Pointer Dereference)

V3080 Possible null dereference. Consider inspecting '_swtFirst'. MemberLookup.cs 109

if (_swtFirst == null)
{
  _swtFirst.Set(sym, type); // <= 
  ....
}

> Pull Request

2. CoreFX. CWE-476 (NULL Pointer Dereference)

V3080 Possible null dereference. Consider inspecting 'tabClasses'. PropertyTabAttribute.cs 225

if (tabClasses != null)                        // <=
{
  if (tabScopes != null && tabClasses.Length != tabScopes.Length)
  {
    ....
  }
  _tabClasses = (Type[])tabClasses.Clone();
}
else if (tabClassNames != null)
{
  if (tabScopes != null &&
      tabClasses.Length != tabScopes.Length)    // <=
  {
    ....
  }
  _tabClassNames = (string[])tabClassNames.Clone();
  _tabClasses = null;
}

> Pull Request

3. CoreFX. CWE-476 (NULL Pointer Dereference)

V3080 Possible null dereference. Consider inspecting 'BaseSimpleType'. SimpleType.cs 368

if ((BaseSimpleType == null && otherSimpleType.BaseSimpleType != null)
    &&
    (BaseSimpleType.HasConflictingDefinition(...)).Length != 0) // <=
    return ("BaseSimpleType");

> Pull Request

4. CoreFX. CWE-476 (NULL Pointer Dereference)

V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'o', 'other'. CompilerInfo.cs 106

CompilerInfo other = o as CompilerInfo;
if (o == null)
{
    return false;
}
return CodeDomProviderType == other.CodeDomProviderType && ... // <=

> Pull Request

5. CoreFX. CWE-476 (NULL Pointer Dereference)

V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'myObject', 'myString'. CaseInsensitiveAscii.cs 46

string myString = myObject as string;
if (myObject == null)
{
    return 0;
}
int myHashCode = myString.Length;      // <=

PVS-Studio: fixed vulnerability CWE-476 (NULL Pointer Dereference)

> Pull Request

6. CoreFX. CWE-476 (NULL Pointer Dereference)

V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'a', 'nodeA'. AttributeSortOrder.cs 22

V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'b', 'nodeB'. AttributeSortOrder.cs 22

XmlNode nodeA = a as XmlNode;
XmlNode nodeB = b as XmlNode;
if ((a == null) || (b == null))
    throw new ArgumentException();
int namespaceCompare =
  string.CompareOrdinal(nodeA.NamespaceURI, nodeB.NamespaceURI); // <=

> Pull Request

7. CoreFX. CWE-476 (NULL Pointer Dereference)

V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'a', 'nodeA'. NamespaceSortOrder.cs 21

V3019 Possibly an incorrect variable is compared to null after type conversion using 'as' keyword. Check variables 'b', 'nodeB'. NamespaceSortOrder.cs 21

XmlNode nodeA = a as XmlNode;
XmlNode nodeB = b as XmlNode;
if ((a == null) || (b == null))
    throw new ArgumentException();
bool nodeAdefault = Utils.IsDefaultNamespaceNode(nodeA); 
bool nodeBdefault = Utils.IsDefaultNamespaceNode(nodeB); 

> Pull Request

8. MSBuild. CWE-476 (NULL Pointer Dereference)

V3095 The 'name' object was used before it was verified against null. Check lines: 229, 235. Microsoft.Build.Tasks GenerateBindingRedirects.cs 229

V3095 The 'publicKeyToken' object was used before it was verified against null. Check lines: 231, 235. Microsoft.Build.Tasks GenerateBindingRedirects.cs 231

private void UpdateExistingBindingRedirects(....)
{
  ....
  var name = assemblyIdentity.Attribute("name");
  var nameValue = name.Value;  // <=
  var publicKeyToken = assemblyIdentity.
                       Attribute("publicKeyToken");
  var publicKeyTokenValue = publicKeyToken.Value;  // <=
  var culture = assemblyIdentity.Attribute("culture");
  var cultureValue = culture == null ? 
                     String.Empty : culture.Value;
  
  if (name == null || publicKeyToken == null)
  {
      continue;
  }  
  ....
}

> Pull Request

Прочие ошибки


1. MSBuild

V3041 The expression was implicitly cast from 'long' type to 'float' type. Consider utilizing an explicit type cast to avoid the loss of a fractional part. An example: double A = (double)(X) / Y;. Microsoft.Build CommunicationsUtilities.cs 615

private static long s_lastLoggedTicks = DateTime.UtcNow.Ticks;
internal static void Trace(....)
{
  ....
  long now = DateTime.UtcNow.Ticks;
  float millisecondsSinceLastLog = 
    (float)((now - s_lastLoggedTicks) / 10000L);
  ....
}

> Pull Request

2. MSBuild

V3118 Milliseconds component of TimeSpan is used, which does not represent full time interval. Possibly 'TotalMilliseconds' value was intended instead. MSBuild XMake.cs 629

public static ExitType Execute(string commandLine)
{
  ....
  if (!String.IsNullOrEmpty(timerOutputFilename))
  {
      AppendOutputFile(timerOutputFilename, 
                        elapsedTime.Milliseconds);
  }
  ....
}

> Pull Request

Заключение


Предлагаем скачать анализатор PVS-Studio и попробовать проверить ваш проект:
Для снятия ограничения демонстрационной версии, вы можете написать нам, и мы отправим вам временный ключ.

Для быстрого знакомства с анализатором, вы можете воспользоваться утилитами, отслеживающими запуски компилятора и собирающие для проверки всю необходимую информацию. См. описание утилиты CLMonitoring и pvs-studio-analyzer. Если вы работаете с классическим типом проекта в Visual Studio, то всё ещё проще: достаточно выбрать в меню PVS-Studio команду «Check Solution».



Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. Vulnerabilities detected by PVS-Studio this week: episode N1.

Прочитали статью и есть вопрос?
Часто к нашим статьям задают одни и те же вопросы. Ответы на них мы собрали здесь: Ответы на вопросы читателей статей про PVS-Studio, версия 2015. Пожалуйста, ознакомьтесь со списком.
Поделиться с друзьями
-->

Комментарии (10)


  1. mad_god
    10.03.2017 17:35
    +2

    Что скажете о недавно раскрытых ЦРУ-уязвимостях в популярных продуктах?


    1. EvgeniyRyzhkov
      10.03.2017 17:36
      +4

      «Мы работаем над этим.» Только тс-с-с-с-с…


      1. lain8dono
        10.03.2017 18:52
        +1

        Ждать проверки эксплоитов на предмет ошибок?


        1. Am0ralist
          11.03.2017 01:21

          на предмет уязвимостей, позволяющих перехватить управление!


  1. lany
    10.03.2017 17:58
    +9

    Всё же вы нос задираете :-) Ошибки — да, уязвимости — нет. Если б каждый NPE превращался в эксплойт, Java и C# давно бы умерли.


    1. Andrey2008
      10.03.2017 19:50
      +3

      Ды понятно… Но раз мир оперирует такими словами, надо адаптироваться. Данные случай является CWE? Является. Данный CWE отмечен, как приводящий к Exploit? Да, причём с уровнем Medium. Всё, значит уязвимость. :)

      Мы конечно пока в этой всей классификации плаваем, но постепенно разберёмся, как правильнее слова использовать.

      И да, я не представляю, как можно это использовать. Но моя задача в первую очередь показать, что мы ловим такие ошибки, а, следовательно, можем выявлять уязвимости.


  1. ryo_oh_ki
    10.03.2017 19:06
    -1

    Не хочется переходить на Visual Studio 2017 пока там не будет PVS-Studio.


    1. Andrey2008
      10.03.2017 19:52
      -1

      Идёт окончательна подготовка и тестирование. Уж очень они много поменяли внутри.


    1. Andrey2008
      17.03.2017 11:31
      +2

      PVS-Studio 6.14. Добавлена поддержка Visual Studio 2017.