Недавно ко мне обратился мой коллега, Андрей Карпов, с просьбой попробовать найти 3-4 ошибки в коде компонентов Tizen на языке C#. Сам он не так давно занимался анализом Tizen на предмет поиска ошибок в C/C++ коде и сейчас пишет несколько статей на эту тему. Вдохновлённый его примером, я провёл эксперимент по поиску ошибок в C# компонентах Tizen. Сразу скажу, что эксперимент прошел удачно, и в дальнейшем я займусь написанием большой статьи на эту тему, а сейчас просто поделюсь результатами пробной проверки.
Для начала я не стал проводить глубокий анализ всей базы исходного кода Tizen, а выбрал пару проектов на языке C#, проверка которых не потребовала бы особых усилий. Цель нашего эксперимента – постараться понять, нужно ли работать в этом направлении.
В результате даже такой поверхностной проверки мне довольно быстро удалось найти несколько реальных ошибок, что позволяет утверждать: здесь есть работа для C# анализатора PVS-Studio. В данной короткой заметке я ограничусь описанием этих ошибок, оставив более подробное изучение данного вопроса на будущее.
По моим подсчётам, код Tizen содержит 4 929 файлов исходного кода с расширением cs, в которых имеется около 691 000 строк кода. Исходный код довольно объёмен и его полноценный анализ потребует некоторого времени. Позже, по результатам этой работы, я напишу развёрнутую статью.
Пока же приведу описание трёх из списка найденных мною на данном этапе работы ошибок. Для простоты я буду указывать имя папки верхнего уровня в иерархии проектов Tizen, где содержался файл с ошибкой.
xamarin-forms-tizen
PVS-Studio: V3001 There are identical sub-expressions 'RwWait' to the left and to the right of the '|' operator. Xamarin.Forms.Platform.WP8 SplitOrderedList.cs 458
struct SimpleRwLock
{
const int RwWait = 1;
const int RwWrite = 2;
const int RwRead = 4;
....
public void EnterReadLock()
{
var sw = new SpinWait();
do
{
while ((_rwlock & (RwWrite | RwWait)) > 0)
sw.SpinOnce();
if ((Interlocked.Add(ref _rwlock, RwRead)
& (RwWait | RwWait)) == 0) // <=
return;
Interlocked.Add(ref _rwlock, -RwRead);
} while (true);
}
....
}
Вероятно, в условии блока if допущена опечатка, связанная с похожестью имен констант RwWait и RwWrite, в результате чего константа RwWait была ошибочно использована дважды. В пользу этого говорит и условие в блоке while выше, где используется правильное сочетание RwWrite | RwWait.
PVS-Studio: V3095 The 'type' object was used before it was verified against null. Check lines: 147, 149. Xamarin.Forms.Xaml ExpandMarkupsVisitor.cs 147
CWE-476 NULL Pointer Dereference
public class MarkupExpansionParser :
MarkupExpressionParser, IExpressionParser<INode>
{
....
public INode Parse(....)
{
....
Type type;
....
var xmltype = new XmlType(namespaceuri, type.Name, null); // <=
if (type == null)
throw new NotSupportedException();
....
}
....
}
Переменную type сначала используют для доступа к type.Name, а уже затем проверяют на равенство null. В результате возможно возникновение исключения типа NullReferenceException.
csapi-location
PVS-Studio. V3110 Possible infinite recursion inside 'Timestamp' property. Tizen.Location Location.cs 186
CWE-674 Uncontrolled Recursion
public class Location
{
....
internal int _timestamp;
....
public DateTime Timestamp
{
get
{
return Interop.ConvertDateTime(_timestamp);
}
internal set
{
Timestamp = value; // <=
}
}
....
}
Данный фрагмент кода содержит ошибку, неизбежно приводящую к исчерпанию стека (бесконечная рекурсия) при попытке доступа на запись к свойству Timestamp. При этом нет видимых признаков опечатки. Поле _timestamp значительно отличается по написанию от Timestamp, так что непохоже, что их могли перепутать. К тому же, _timestamp имеет тип int, что делает невозможным прямое присвоение ему значения value типа DateTime. Потребовалось бы преобразование типа, наподобие того, что реализовано в секции get. Думаю, исправить данную ошибку смог бы только автор.
Думаю, для начала достаточно, остальные ошибки, найденные на этом этапе, я приберегу для следующей статьи.
Можно сделать вывод, что анализатор PVS-Studio может быть использован не только для проверки C и C++ кода, но и для проверки компонентов, разработанных на C#.
Скачать и попробовать PVS-Studio: http://www.viva64.com/ru/pvs-studio/
Дополнительные ссылки: