SlideShare uma empresa Scribd logo
1 de 9
Baixar para ler offline
Статический анализ: ошибки в
медиаплеере и безглючная аська
Автор: Андрей Карпов

Дата: 18.11.2010

Продолжу экскурсию по ошибкам в программах и демонстрацию полезности статического
анализа кода.

Это мой последний пост про пока недоступную для скачиванию версию PVS-Studio. Планирую, что
через неделю вы уже сможете попробовать первую beta-версию с новым набором правил общего
назначения.

Рассмотрим два проекта. Первый - Fennec Media Project. Это универсальный медиа-плеер
ориентированный на воспроизведение аудио и видео в высоком разрешении. В комплект
исходных кодов входит множество модулей расширения (plugins) и кодеков, но анализироваться
будет только сам плеер. Исходный код последней на данный момент версии 1.2 Alpha доступен
здесь.

Второй проект - qutIM. Это кроссплатформенный клиент мгновенного обмена сообщениями с
открытым исходным кодом. Был проанализирован код на момент начала ноября 2010 года. Набор
исходных кодов был предоставлен мне одним из разработчиков, но вы также можете скачать
исходный код с официального сайта.

Fennec Media Project. Небольшой нормальный проект, содержащий нормальное количество
ошибок. Вот первая ошибка. Или первые две ошибки, смотря как считать. В общем, в двух местах
вместо переменной 'b' используется переменная 'a'.

int fennec_tag_item_compare(struct fennec_audiotag_item *a,

    struct fennec_audiotag_item *b)

{

    int v;

    if(a->tsize && a->tsize)

     v = abs(str_cmp(a->tdata, a->tdata));

    else

     v = 1;

    return v;

}

PVS-Studio указал на этот код, так как условие "a->tsize && a->tsize" явно подозрительно.

Диагностическое сообщение и местоположение ошибки в коде:
V501 There are identical sub-expressions to the left and to the right of the '&&' operator: a -> tsize && a
-> tsize media library.c 1076

А теперь родное и милое сердцу каждого программиста - лишние точки с запятой. Вот первый
фрагмент:

int settings_default(void)

{

    ...

    for(i=0; i<16; i++);

        for(j=0; j<32; j++)

        {

            settings.conversion.equalizer_bands.boost[i][j] = 0.0;

            settings.conversion.equalizer_bands.preamp[i]                        = 0.0;

        }

}

Сообщение PVS-Studio и местоположение коде:

V529 Odd semicolon ';' after 'for' operator. settings.c 483

Второй фрагмент:

int trans_rest(transcoder_settings *trans)

{

    ...

    for(i=0; i<16; i++);

    {

        trans->eq.eq.preamp[i]             = 0.0;

        for(j=0; j<32; j++)

        {

            trans->eq.eq.boost[i][j] = 0.0;

        }

    }

}

Сообщение PVS-Studio и местоположение коде:
V529 Odd semicolon ';' after 'for' operator. settings.c 913

Есть еще третий и четвертый фрагмент с ';'. Но приводить здесь не буду. Все однотипно и
неинтересно.

Дальше не совсем ошибка, но почти. Вместо функции _beginthreadex используется CreateThread.
Вызовов CreateThread в Fennec несколько, но приведу только один пример:

t_sys_thread_handle sys_thread_call(t_sys_thread_function cfunc)
{
  unsigned long tpr = 0;
  unsigned long tid = 0;
  return (t_sys_thread_handle)
    CreateThread(0, 0, cfunc, &tpr, 0,&tid);
}

Предупреждение PVS-Studio и местоположение коде:

V513 Use _beginthreadex/_endthreadex functions instead of CreateThread/ExitThread functions.
system.c 331

Вдаваться сейчас вглубь вопроса, почему следует использовать _beginthreadex/_endthreadex
вместо CreateThread/ExitThread, не буду. Напишу совсем кратко, а подробные обсуждения
данного вопроса можно почитать здесь, здесь и здесь.

В священном писании (в MSDN) сказано:

A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and
_endthreadex functions for thread management rather than CreateThread and ExitThread; this requires
the use of the multi-threaded version of the CRT. If a thread created using CreateThread calls the CRT,
the CRT may terminate the process in low-memory conditions.

В общем лучше подстраховаться и всегда вызывать именно _beginthreadex/_endthreadex. Кстати
именно так рекомендует поступать и Джеффри Рихтера в шестой главе "Windows для
профессионалов: создание эффективных Win32-приложений с учетом специфики 64-разрядной
версии Windows" / Пер. с англ. - 4-е изд.

Обнаружилось несколько неудачных использований функции memset. Кстати, я до недавнего
времени думал, что беспокойство, связанное с использованием memset, memcmp, memcpy – дело
прошлого. Мол, это раньше так писали, но сейчас все знают про опасности, аккуратны с этими
функциями, используют sizeof(), используют контейнеры из STL и так далее. А сейчас все розовое и
мягкое. Оказывается, что нет. Я за последний месяц столько ляпов с этими функциями
насмотрелся. Так что все эти ошибки по-прежнему цветут и пахнут.

Вернемся в Fennec. Первый memset:

#define uinput_size                   1024

typedef wchar_t letter;



letter     uinput_text[uinput_size];
string basewindows_getuserinput(const string title,

    const string cap, const string dtxt)

{

    memset(uinput_text, 0, uinput_size);

    ...

}

Диагностика PVS-Studio и местоположение коде:

V512 A call of the 'memset' function will lead to a buffer overflow or underflow. base windows.c 151

На первый взгляд с "memset(uinput_text, 0, uinput_size);" все хорошо. И возможно даже и было
хорошо, в те времена, когда тип 'letter' был 'char'. Но теперь это 'wchar_t' и как результат мы
чистим только половину буфера.

Второй неудачный memset:

typedef wchar_t letter;

letter name[30];



int Conv_EqualizerProc(HWND hwnd,UINT uMsg,

    WPARAM wParam,LPARAM lParam)

{

    ...

    memset(eqp.name, 0, 30);

    ...

}

Воистину магические числа – это зло. Вроде и не сложно написать "sizeof(eqp.name)". Но упорно
не пишем и продолжаем вновь и вновь отстреливать себе ногу :).

Диагностика PVS-Studio и местоположение коде:

V512 A call of the 'memset' function will lead to a buffer overflow or underflow. base windows.c 2892

Ну и еще в одном месте такая шибка есть:

V512 A call of the 'memset' function will lead to a buffer overflow or underflow. transcode settings.c
588
Возможно, иногда в каких-то программах вы замечали, что диалоги открытия/сохранения файлов
работают со странностями или в полях доступных расширений присутствует какая-то чушь. Сейчас
вы узнаете, откуда у этого растут ноги.

В Windows API есть структуры, в которых указатели на строки должны заканчиваться двойным
нулем. Наиболее используемым является член lpstrFilter в структуре OPENFILENAME. Этот
параметр на самом деле указывает на набор строк, разделенных символом '0'. А для того чтобы
узнать, что строки закончились и нужны два нуля в конце.

Вот только это очень просто забыть. Фрагмент кода:

int JoiningProc(HWND hwnd,UINT uMsg,

    WPARAM wParam,LPARAM lParam)

{

    ...

    OPENFILENAME      lofn;

    memset(&lofn, 0, sizeof(lofn));

    ...

    lofn.lpstrFilter = uni("All Files (*.*)0*.*");

    ...

}

Сообщение PVS-Studio и местоположение коде:

V540 Member 'lpstrFilter' should point to string terminated by two 0 characters. base windows.c 5309

Будет диалог работать нормально или нет, зависит от того, что будет расположено в памяти после
строки "All Files (*.*)0*.*". По правильному здесь следовало написать "All Files (*.*)0*.*0". Один
ноль явно указали мы, еще один ноль добавит компилятор.

Аналогичная беда и с другими диалогами.

int callback_presets_dialog(HWND hwnd, UINT msg,

    WPARAM wParam, LPARAM lParam)

{

    ...

    // SAVE

    OPENFILENAME lofn;

    memset(&lofn, 0, sizeof(lofn));

    ...
lofn.lpstrFilter = uni("Equalizer Preset (*.feq)0*.feq");

    ...

    ...

    // LOAD

    ...

    lofn.lpstrFilter = uni("Equalizer Preset (*.feq)0*.feq");

    ...

}

int localsf_show_save_playlist(void)

{

    OPENFILENAME       lofn;

    memset(&lofn, 0, sizeof(lofn));

    ...

    lofn.lpstrFilter = uni("Text file (*.txt)0*.txt0M3U file0*.m3u");

    ...

}

Диагностика PVS-Studio и местоположение в коде:

V540 Member 'lpstrFilter' should point to string terminated by two 0 characters. base windows.c 986

V540 Member 'lpstrFilter' should point to string terminated by two 0 characters. base windows.c 1039

V540 Member 'lpstrFilter' should point to string terminated by two 0 characters. shared functions.c
360

Теперь подозрительная функция. Очень подозрительная. Впрочем, действительно тут ошибка или
просто неудачно написано, я не знаю:

unsigned long ml_cache_getcurrent_item(void)

{

    if(!mode_ml)

     return skin.shared->audio.output.playlist.getcurrentindex();

    else

     return skin.shared->audio.output.playlist.getcurrentindex();

}
Диагностика PVS-Studio и местоположение в коде:

V523 The 'then' statement is equivalent to the 'else' statement. media library window.c 430

Я не стал заниматься анализом разнообразный модулей расширений, идущих вместе с Fennec. Но
там не меньше разных грустных мест. Приведу только пару примеров. Фрагмент кода из проекта
Codec ACC.

void MP4RtpHintTrack::GetPayload(...)

{

    ...

    if (pSlash != NULL) {

        pSlash++;

        if (pSlash != '0') {

            length = strlen(pRtpMap) - (pSlash - pRtpMap);

            *ppEncodingParams = (char *)MP4Calloc(length + 1);

            strncpy(*ppEncodingParams, pSlash, length);

        }

}

Как следует из диагностического сообщения PVS-Studio:

V528 It is odd that pointer to 'char' type is compared with the '0' value. Probably meant: *pSlash !=
'0'. rtphint.cpp 346

здесь забыли разыменовать указатель. Получается, что мы делаем бессмысленное сравнение
указателя с 0. Должно было быть: "if (*pSlash != '0')".

Фрагмент кода из проекта Decoder Mpeg Audio:

void* tag_write_setframe(char *tmem,

    const char *tid, const string dstr)

{

    ...

    if(lset)

    {

        fhead[11] = '0';

        fhead[12] = '0';

        fhead[13] = '0';
fhead[13] = '0';

    }

    ...

}

Диагностическое сообщение PVS-Studio и местоположение в коде:

V525 The code containing the collection of similar blocks. Check items '11', '12', '13', '13' in lines 716,
717, 718, 719. id3 editor.c 716

Вот оно зло метода Copy-Paste :).

В целом на проекте Fennec Media Project анализ общего назначения в PVS-Studio показал себя
очень хорошо. Анализ был выполнен с низким процентом ложных срабатываний. Всего PVS-Studio
указал на 31 фрагмент кода. При этом в 19 местах код действительно следует поправить.

Теперь перейдем к проекту qutIM.

Вот с эти проектом PVS-Studio потерпел поражение. Несмотря на то, что проект достаточно
крупный (около 200 тысяч сток), анализатор PVS-Studio не смог выявить в нем ошибок. Хотя они
конечно есть. Они везде и всегда есть :). И разработчики qutIM с этим не спорят, так как в
некоторых случаях qutIM умудряется падать.

Приходится засчитать одно очко "команде ошибок".

Что это означает? Это означает:

1) Проект qutIM очень качественный проект. И хотя он тоже содержит ошибки, но они весьма
редки и слишком высокого уровня для статического анализа (по крайней мере, для PVS-Studio).

2) PVS-Studio предстоит еще долгий путь развития и обучения более высокоуровневым
диагностикам. Теперь стало более очевидно к чему стремиться. Цель - найти в qutIM хотя бы
парочку настоящих ошибок.

Выдал ли что-то PVS-Studio для проекта qutIM? Выдал. Но немного и почти все ложные
срабатывания. Их представляющего хоть какой-то интерес, можно выделить только следующее.

A) Используются функции CreateThread.

B) Найдено несколько странных функций. Потом один из авторов qutIM сообщил, что это забытые
заглушки. Странность в том, что одна имеет имя save(), другая cancel(), но их содержимое
идентично:



void XSettingsWindow::save()

{

    QWidget *c = p->stackedWidget->currentWidget();

    while (p->modifiedWidgets.count()) {
SettingsWidget *widget = p->modifiedWidgets.takeFirst();

        widget->save();

        if (widget != c)

         widget->deleteLater();

    }

    p->buttonBox->close();

}



void XSettingsWindow::cancel()

{

    QWidget *c = p->stackedWidget->currentWidget();

    while (p->modifiedWidgets.count()) {

        SettingsWidget *widget = p->modifiedWidgets.takeFirst();

        widget->save();

        if (widget != c)

         widget->deleteLater();

    }

    p->buttonBox->close();

}

Диагностика PVS-Studio:

V524 It is odd that the 'cancel' function is fully equivalent to the 'save' function (xsettingswindow.cpp,
line 256). xsettingswindow.cpp 268

Надеюсь было интересно, и вы скоро захотите попробовать PVS-Studio 4.00 Beta. Конечно, PVS-
Studio пока находит мало ошибок общего вида, но ведь это только начало. При этом исправление
даже одной единственной ошибки на этапе кодирования может сэкономить массу нервов
заказчикам, тестерам и программистам.

Mais conteúdo relacionado

Mais procurados

Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templates
Platonov Sergey
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Mikhail Kurnosov
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
victor-yastrebov
 

Mais procurados (19)

Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
 
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
 
Intel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибкамиIntel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибками
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templates
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
 
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
 
Особенности создания XS-модулей на языке C++. Владимир Тимофеев. Moscow.pm 4 ...
Особенности создания XS-модулей на языке C++. Владимир Тимофеев. Moscow.pm 4 ...Особенности создания XS-модулей на языке C++. Владимир Тимофеев. Moscow.pm 4 ...
Особенности создания XS-модулей на языке C++. Владимир Тимофеев. Moscow.pm 4 ...
 
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программированияПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
 
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
 
хитрости выведения типов
хитрости выведения типовхитрости выведения типов
хитрости выведения типов
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6
 
Вечный вопрос измерения времени
Вечный вопрос измерения времениВечный вопрос измерения времени
Вечный вопрос измерения времени
 
Модель памяти C++ - Андрей Янковский, Яндекс
Модель памяти C++ - Андрей Янковский, ЯндексМодель памяти C++ - Андрей Янковский, Яндекс
Модель памяти C++ - Андрей Янковский, Яндекс
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
 
Семинар 9. Параллельное программирование на MPI (часть 2)
Семинар 9. Параллельное программирование на MPI (часть 2)Семинар 9. Параллельное программирование на MPI (часть 2)
Семинар 9. Параллельное программирование на MPI (часть 2)
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMP
 

Destaque (12)

introducción a Machine Learning
introducción a Machine Learningintroducción a Machine Learning
introducción a Machine Learning
 
Критерий Гурвица
Критерий ГурвицаКритерий Гурвица
Критерий Гурвица
 
Bi mat cua may man
Bi mat cua may manBi mat cua may man
Bi mat cua may man
 
Unidad iii informatica
Unidad iii  informaticaUnidad iii  informatica
Unidad iii informatica
 
SPICE MODEL of EP05Q04 (Standard Model) in SPICE PARK
SPICE MODEL of EP05Q04 (Standard Model) in SPICE PARKSPICE MODEL of EP05Q04 (Standard Model) in SPICE PARK
SPICE MODEL of EP05Q04 (Standard Model) in SPICE PARK
 
Internet Marketing Consultant
Internet Marketing ConsultantInternet Marketing Consultant
Internet Marketing Consultant
 
Paradigmas de la educación
Paradigmas de la educaciónParadigmas de la educación
Paradigmas de la educación
 
Presentación Porta retrato-Reciclaje
Presentación Porta retrato-ReciclajePresentación Porta retrato-Reciclaje
Presentación Porta retrato-Reciclaje
 
Pie chart with center 12 stages powerpoint diagrams and powerpoint templates
Pie chart with center 12 stages powerpoint diagrams and powerpoint templatesPie chart with center 12 stages powerpoint diagrams and powerpoint templates
Pie chart with center 12 stages powerpoint diagrams and powerpoint templates
 
Sad 1 chapter 1- additional material
Sad 1 chapter 1- additional materialSad 1 chapter 1- additional material
Sad 1 chapter 1- additional material
 
07money
07money07money
07money
 
Nematomorpha
Nematomorpha Nematomorpha
Nematomorpha
 

Semelhante a Статический анализ: ошибки в медиаплеере и безглючная аська

ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кода
Andrey Karpov
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
Andrey Karpov
 
Low-level C/C++ Optimization by Anrew Axenov (Sphinx)
Low-level C/C++ Optimization by Anrew Axenov (Sphinx)Low-level C/C++ Optimization by Anrew Axenov (Sphinx)
Low-level C/C++ Optimization by Anrew Axenov (Sphinx)
Vadim Kosov
 
Низкоуровневая Оптимизация (Андрей Аксенов)
Низкоуровневая Оптимизация (Андрей Аксенов)Низкоуровневая Оптимизация (Андрей Аксенов)
Низкоуровневая Оптимизация (Андрей Аксенов)
Ontico
 
Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templates
Platonov Sergey
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
Michael Karpov
 

Semelhante a Статический анализ: ошибки в медиаплеере и безглючная аська (20)

Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кода
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кода
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложений
 
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 
Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментом
 
Статический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeСтатический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMerge
 
Эффективный C++
Эффективный C++Эффективный C++
Эффективный C++
 
Low-level C/C++ Optimization by Anrew Axenov (Sphinx)
Low-level C/C++ Optimization by Anrew Axenov (Sphinx)Low-level C/C++ Optimization by Anrew Axenov (Sphinx)
Low-level C/C++ Optimization by Anrew Axenov (Sphinx)
 
Cpp
CppCpp
Cpp
 
Низкоуровневая Оптимизация (Андрей Аксенов)
Низкоуровневая Оптимизация (Андрей Аксенов)Низкоуровневая Оптимизация (Андрей Аксенов)
Низкоуровневая Оптимизация (Андрей Аксенов)
 
Transpile it.pdf
Transpile it.pdfTranspile it.pdf
Transpile it.pdf
 
Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templates
 
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
 
Пояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteПояснения к статье про Copy-Paste
Пояснения к статье про Copy-Paste
 
Урок 24. Фантомные ошибки
Урок 24. Фантомные ошибкиУрок 24. Фантомные ошибки
Урок 24. Фантомные ошибки
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMP
 

Mais de Tatyanazaxarova

Mais de Tatyanazaxarova (20)

Урок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окруженияУрок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окружения
 
Урок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программУрок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программ
 
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибокУрок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
 
Урок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структурУрок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структур
 
Урок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данныхУрок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данных
 
Урок 20. Паттерн 12. Исключения
Урок 20. Паттерн 12. ИсключенияУрок 20. Паттерн 12. Исключения
Урок 20. Паттерн 12. Исключения
 
Урок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен даннымиУрок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен данными
 
Урок 17. Паттерн 9. Смешанная арифметика
Урок 17. Паттерн 9. Смешанная арифметикаУрок 17. Паттерн 9. Смешанная арифметика
Урок 17. Паттерн 9. Смешанная арифметика
 
Урок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединенияхУрок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединениях
 
Урок 15. Паттерн 7. Упаковка указателей
Урок 15. Паттерн 7. Упаковка указателейУрок 15. Паттерн 7. Упаковка указателей
Урок 15. Паттерн 7. Упаковка указателей
 
Урок 13. Паттерн 5. Адресная арифметика
Урок 13. Паттерн 5. Адресная арифметикаУрок 13. Паттерн 5. Адресная арифметика
Урок 13. Паттерн 5. Адресная арифметика
 
Урок 11. Паттерн 3. Операции сдвига
Урок 11. Паттерн 3. Операции сдвигаУрок 11. Паттерн 3. Операции сдвига
Урок 11. Паттерн 3. Операции сдвига
 
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументовУрок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
 
Урок 9. Паттерн 1. Магические числа
Урок 9. Паттерн 1. Магические числаУрок 9. Паттерн 1. Магические числа
Урок 9. Паттерн 1. Магические числа
 
Урок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибокУрок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибок
 
Урок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибокУрок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибок
 
Урок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном кодеУрок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном коде
 
Урок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложенияУрок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложения
 
Урок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурацииУрок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурации
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложений
 

Último

Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Ирония безопасности
 
Cyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdfCyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdf
Хроники кибер-безопасника
 
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
Ирония безопасности
 
2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf
Хроники кибер-безопасника
 
CVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdfCVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdf
Хроники кибер-безопасника
 
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdfСИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
Хроники кибер-безопасника
 

Último (9)

MS Navigating Incident Response [RU].pdf
MS Navigating Incident Response [RU].pdfMS Navigating Incident Response [RU].pdf
MS Navigating Incident Response [RU].pdf
 
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
 
Ransomware_Q3 2023. The report [RU].pdf
Ransomware_Q3 2023.  The report [RU].pdfRansomware_Q3 2023.  The report [RU].pdf
Ransomware_Q3 2023. The report [RU].pdf
 
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdfMalware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
 
Cyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdfCyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdf
 
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
 
2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf
 
CVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdfCVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdf
 
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdfСИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
 

Статический анализ: ошибки в медиаплеере и безглючная аська

  • 1. Статический анализ: ошибки в медиаплеере и безглючная аська Автор: Андрей Карпов Дата: 18.11.2010 Продолжу экскурсию по ошибкам в программах и демонстрацию полезности статического анализа кода. Это мой последний пост про пока недоступную для скачиванию версию PVS-Studio. Планирую, что через неделю вы уже сможете попробовать первую beta-версию с новым набором правил общего назначения. Рассмотрим два проекта. Первый - Fennec Media Project. Это универсальный медиа-плеер ориентированный на воспроизведение аудио и видео в высоком разрешении. В комплект исходных кодов входит множество модулей расширения (plugins) и кодеков, но анализироваться будет только сам плеер. Исходный код последней на данный момент версии 1.2 Alpha доступен здесь. Второй проект - qutIM. Это кроссплатформенный клиент мгновенного обмена сообщениями с открытым исходным кодом. Был проанализирован код на момент начала ноября 2010 года. Набор исходных кодов был предоставлен мне одним из разработчиков, но вы также можете скачать исходный код с официального сайта. Fennec Media Project. Небольшой нормальный проект, содержащий нормальное количество ошибок. Вот первая ошибка. Или первые две ошибки, смотря как считать. В общем, в двух местах вместо переменной 'b' используется переменная 'a'. int fennec_tag_item_compare(struct fennec_audiotag_item *a, struct fennec_audiotag_item *b) { int v; if(a->tsize && a->tsize) v = abs(str_cmp(a->tdata, a->tdata)); else v = 1; return v; } PVS-Studio указал на этот код, так как условие "a->tsize && a->tsize" явно подозрительно. Диагностическое сообщение и местоположение ошибки в коде:
  • 2. V501 There are identical sub-expressions to the left and to the right of the '&&' operator: a -> tsize && a -> tsize media library.c 1076 А теперь родное и милое сердцу каждого программиста - лишние точки с запятой. Вот первый фрагмент: int settings_default(void) { ... for(i=0; i<16; i++); for(j=0; j<32; j++) { settings.conversion.equalizer_bands.boost[i][j] = 0.0; settings.conversion.equalizer_bands.preamp[i] = 0.0; } } Сообщение PVS-Studio и местоположение коде: V529 Odd semicolon ';' after 'for' operator. settings.c 483 Второй фрагмент: int trans_rest(transcoder_settings *trans) { ... for(i=0; i<16; i++); { trans->eq.eq.preamp[i] = 0.0; for(j=0; j<32; j++) { trans->eq.eq.boost[i][j] = 0.0; } } } Сообщение PVS-Studio и местоположение коде:
  • 3. V529 Odd semicolon ';' after 'for' operator. settings.c 913 Есть еще третий и четвертый фрагмент с ';'. Но приводить здесь не буду. Все однотипно и неинтересно. Дальше не совсем ошибка, но почти. Вместо функции _beginthreadex используется CreateThread. Вызовов CreateThread в Fennec несколько, но приведу только один пример: t_sys_thread_handle sys_thread_call(t_sys_thread_function cfunc) { unsigned long tpr = 0; unsigned long tid = 0; return (t_sys_thread_handle) CreateThread(0, 0, cfunc, &tpr, 0,&tid); } Предупреждение PVS-Studio и местоположение коде: V513 Use _beginthreadex/_endthreadex functions instead of CreateThread/ExitThread functions. system.c 331 Вдаваться сейчас вглубь вопроса, почему следует использовать _beginthreadex/_endthreadex вместо CreateThread/ExitThread, не буду. Напишу совсем кратко, а подробные обсуждения данного вопроса можно почитать здесь, здесь и здесь. В священном писании (в MSDN) сказано: A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multi-threaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions. В общем лучше подстраховаться и всегда вызывать именно _beginthreadex/_endthreadex. Кстати именно так рекомендует поступать и Джеффри Рихтера в шестой главе "Windows для профессионалов: создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows" / Пер. с англ. - 4-е изд. Обнаружилось несколько неудачных использований функции memset. Кстати, я до недавнего времени думал, что беспокойство, связанное с использованием memset, memcmp, memcpy – дело прошлого. Мол, это раньше так писали, но сейчас все знают про опасности, аккуратны с этими функциями, используют sizeof(), используют контейнеры из STL и так далее. А сейчас все розовое и мягкое. Оказывается, что нет. Я за последний месяц столько ляпов с этими функциями насмотрелся. Так что все эти ошибки по-прежнему цветут и пахнут. Вернемся в Fennec. Первый memset: #define uinput_size 1024 typedef wchar_t letter; letter uinput_text[uinput_size];
  • 4. string basewindows_getuserinput(const string title, const string cap, const string dtxt) { memset(uinput_text, 0, uinput_size); ... } Диагностика PVS-Studio и местоположение коде: V512 A call of the 'memset' function will lead to a buffer overflow or underflow. base windows.c 151 На первый взгляд с "memset(uinput_text, 0, uinput_size);" все хорошо. И возможно даже и было хорошо, в те времена, когда тип 'letter' был 'char'. Но теперь это 'wchar_t' и как результат мы чистим только половину буфера. Второй неудачный memset: typedef wchar_t letter; letter name[30]; int Conv_EqualizerProc(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam) { ... memset(eqp.name, 0, 30); ... } Воистину магические числа – это зло. Вроде и не сложно написать "sizeof(eqp.name)". Но упорно не пишем и продолжаем вновь и вновь отстреливать себе ногу :). Диагностика PVS-Studio и местоположение коде: V512 A call of the 'memset' function will lead to a buffer overflow or underflow. base windows.c 2892 Ну и еще в одном месте такая шибка есть: V512 A call of the 'memset' function will lead to a buffer overflow or underflow. transcode settings.c 588
  • 5. Возможно, иногда в каких-то программах вы замечали, что диалоги открытия/сохранения файлов работают со странностями или в полях доступных расширений присутствует какая-то чушь. Сейчас вы узнаете, откуда у этого растут ноги. В Windows API есть структуры, в которых указатели на строки должны заканчиваться двойным нулем. Наиболее используемым является член lpstrFilter в структуре OPENFILENAME. Этот параметр на самом деле указывает на набор строк, разделенных символом '0'. А для того чтобы узнать, что строки закончились и нужны два нуля в конце. Вот только это очень просто забыть. Фрагмент кода: int JoiningProc(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam) { ... OPENFILENAME lofn; memset(&lofn, 0, sizeof(lofn)); ... lofn.lpstrFilter = uni("All Files (*.*)0*.*"); ... } Сообщение PVS-Studio и местоположение коде: V540 Member 'lpstrFilter' should point to string terminated by two 0 characters. base windows.c 5309 Будет диалог работать нормально или нет, зависит от того, что будет расположено в памяти после строки "All Files (*.*)0*.*". По правильному здесь следовало написать "All Files (*.*)0*.*0". Один ноль явно указали мы, еще один ноль добавит компилятор. Аналогичная беда и с другими диалогами. int callback_presets_dialog(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ... // SAVE OPENFILENAME lofn; memset(&lofn, 0, sizeof(lofn)); ...
  • 6. lofn.lpstrFilter = uni("Equalizer Preset (*.feq)0*.feq"); ... ... // LOAD ... lofn.lpstrFilter = uni("Equalizer Preset (*.feq)0*.feq"); ... } int localsf_show_save_playlist(void) { OPENFILENAME lofn; memset(&lofn, 0, sizeof(lofn)); ... lofn.lpstrFilter = uni("Text file (*.txt)0*.txt0M3U file0*.m3u"); ... } Диагностика PVS-Studio и местоположение в коде: V540 Member 'lpstrFilter' should point to string terminated by two 0 characters. base windows.c 986 V540 Member 'lpstrFilter' should point to string terminated by two 0 characters. base windows.c 1039 V540 Member 'lpstrFilter' should point to string terminated by two 0 characters. shared functions.c 360 Теперь подозрительная функция. Очень подозрительная. Впрочем, действительно тут ошибка или просто неудачно написано, я не знаю: unsigned long ml_cache_getcurrent_item(void) { if(!mode_ml) return skin.shared->audio.output.playlist.getcurrentindex(); else return skin.shared->audio.output.playlist.getcurrentindex(); }
  • 7. Диагностика PVS-Studio и местоположение в коде: V523 The 'then' statement is equivalent to the 'else' statement. media library window.c 430 Я не стал заниматься анализом разнообразный модулей расширений, идущих вместе с Fennec. Но там не меньше разных грустных мест. Приведу только пару примеров. Фрагмент кода из проекта Codec ACC. void MP4RtpHintTrack::GetPayload(...) { ... if (pSlash != NULL) { pSlash++; if (pSlash != '0') { length = strlen(pRtpMap) - (pSlash - pRtpMap); *ppEncodingParams = (char *)MP4Calloc(length + 1); strncpy(*ppEncodingParams, pSlash, length); } } Как следует из диагностического сообщения PVS-Studio: V528 It is odd that pointer to 'char' type is compared with the '0' value. Probably meant: *pSlash != '0'. rtphint.cpp 346 здесь забыли разыменовать указатель. Получается, что мы делаем бессмысленное сравнение указателя с 0. Должно было быть: "if (*pSlash != '0')". Фрагмент кода из проекта Decoder Mpeg Audio: void* tag_write_setframe(char *tmem, const char *tid, const string dstr) { ... if(lset) { fhead[11] = '0'; fhead[12] = '0'; fhead[13] = '0';
  • 8. fhead[13] = '0'; } ... } Диагностическое сообщение PVS-Studio и местоположение в коде: V525 The code containing the collection of similar blocks. Check items '11', '12', '13', '13' in lines 716, 717, 718, 719. id3 editor.c 716 Вот оно зло метода Copy-Paste :). В целом на проекте Fennec Media Project анализ общего назначения в PVS-Studio показал себя очень хорошо. Анализ был выполнен с низким процентом ложных срабатываний. Всего PVS-Studio указал на 31 фрагмент кода. При этом в 19 местах код действительно следует поправить. Теперь перейдем к проекту qutIM. Вот с эти проектом PVS-Studio потерпел поражение. Несмотря на то, что проект достаточно крупный (около 200 тысяч сток), анализатор PVS-Studio не смог выявить в нем ошибок. Хотя они конечно есть. Они везде и всегда есть :). И разработчики qutIM с этим не спорят, так как в некоторых случаях qutIM умудряется падать. Приходится засчитать одно очко "команде ошибок". Что это означает? Это означает: 1) Проект qutIM очень качественный проект. И хотя он тоже содержит ошибки, но они весьма редки и слишком высокого уровня для статического анализа (по крайней мере, для PVS-Studio). 2) PVS-Studio предстоит еще долгий путь развития и обучения более высокоуровневым диагностикам. Теперь стало более очевидно к чему стремиться. Цель - найти в qutIM хотя бы парочку настоящих ошибок. Выдал ли что-то PVS-Studio для проекта qutIM? Выдал. Но немного и почти все ложные срабатывания. Их представляющего хоть какой-то интерес, можно выделить только следующее. A) Используются функции CreateThread. B) Найдено несколько странных функций. Потом один из авторов qutIM сообщил, что это забытые заглушки. Странность в том, что одна имеет имя save(), другая cancel(), но их содержимое идентично: void XSettingsWindow::save() { QWidget *c = p->stackedWidget->currentWidget(); while (p->modifiedWidgets.count()) {
  • 9. SettingsWidget *widget = p->modifiedWidgets.takeFirst(); widget->save(); if (widget != c) widget->deleteLater(); } p->buttonBox->close(); } void XSettingsWindow::cancel() { QWidget *c = p->stackedWidget->currentWidget(); while (p->modifiedWidgets.count()) { SettingsWidget *widget = p->modifiedWidgets.takeFirst(); widget->save(); if (widget != c) widget->deleteLater(); } p->buttonBox->close(); } Диагностика PVS-Studio: V524 It is odd that the 'cancel' function is fully equivalent to the 'save' function (xsettingswindow.cpp, line 256). xsettingswindow.cpp 268 Надеюсь было интересно, и вы скоро захотите попробовать PVS-Studio 4.00 Beta. Конечно, PVS- Studio пока находит мало ошибок общего вида, но ведь это только начало. При этом исправление даже одной единственной ошибки на этапе кодирования может сэкономить массу нервов заказчикам, тестерам и программистам.