Оценка (не)покрытия кода по результатам динамического анализа

Создание любого ПО сопровождается ошибками. Программисты ошибаются в выборе типов, ошибаются в реализации алгоритмов. Аналитики ошибаются в формулировке требований к ПО, и из этих ошибок рождаются ошибки в функционировании готового продукта. Любой (ну ладно, почти любой) производитель программных продуктов хочет обезопасить себя от ошибок в выпускаемом ПО. Для того чтобы избежать типовых ошибок, придумали различные стандарты (типа MISRA C) и утилиты для анализа написанного кода (например, Lint). Но корректно написанный код — это половина проблемы, вторая половина — это насколько верно и полно код реализует требования к программе, и нет ли в программе того, чего там быть не должно. Ответ на эти вопросы в свою очередь дает тестирование и проверка покрытия кода (например, gcov).
Иногда, в случае если программное обеспечение является частью системы, имеющей повышенные требования к безопасности, например, в авионике, требуется доказать, что весь код на уровне исполняемого образа программы корректен и не содержит «лишнего». Вот тут-то и необходимо задействовать весь выше озвученный арсенал средств и засесть за анализ того, что получилось из исходного кода.
Анализ кода и варианты сбора данных о покрытии.
Прежде всего давайте рассмотрим, какие у нас вообще есть наиболее употребимые варианты анализа кода. Их два: динамический и статический.
Статический анализ производится различными утилитами и не предполагает исполнения анализируемого кода. Это отдельная большая тема, и мы ее здесь затрагивать не будем.
Динамический анализ кода — это способ анализа работы программы на основании результатов, собранных непосредственно при ее выполнении.
Сам процесс динамического анализа может быть разделен на этапы:
- Подготовка исходных данных — тестовых векторов для программы;
- Инструментирование — добавление к коду программы дополнительного функционала, позволяющего собрать требуемые данные;
- Проведение тестового запуска программы на основании тестовых векторов, сформированных в пункте 1;
- Сбор результатов исполнения и их анализ.
То есть программа должна быть собрана, дополнена инструментированием и запущена. В ходе выполнения программы на основе тестовых векторов будут собраны и сохранены данные, которые в дальнейшем могут быть использованы чтобы понять, как работает эта программа.
Динамический анализ может преследовать различные цели. Он может быть использован для обнаружения «узких мест» в исполнении программы на конкретном железе, для оценки внутренних механизмов и путей исполнения (трассы), для реверс-инжиниринга и для оценки полноты и достаточности кода для реализации требуемого функционала.
Вот как раз о последнем применении хочется поговорить подробнее.
Динамическое покрытие кода и его анализ.
В идеальном мире программа — это инженерный продукт, служащий для выполнения определенных функций. Необходимый функционал определяется требованиями к программному обеспечению. Процесс создания ПО — это воплощение программистами требований в некий код, который выполняется на ЭВМ.
Дальше, для простоты, я буду рассматривать ситуацию, когда программный код написан на компилируемом языке высокого уровня (допустим С).
Инструментировать и собирать данные о покрытии в этом случае можно на нескольких уровнях. Например, на уровне самого языка. Таким образом, можно увидеть, какие конструкции покрыты, какие не покрыты, какие условия оценивались, а какие нет и т.д. Можно инструментировать на уровне объектного кода или промежуточного ассемблера. Каждый из этих методов имеет свои особенности, преимущества и недостатки. Но пока давайте вернемся к процессу получения знаний о том, как наш код работает.
Итак, программа собрана, запущена и вроде как даже делает то, что надо. Часто на данном этапе все участники счастливы (поляна накрыта, документы подписаны).
Однако, в случае если, допустим, управляемая ПО система предъявляет какие-нибудь мало-мальски серьезные требования к безопасности и/или надежности, то как раз на этом этапе начинается самое интересное. Могут возникнуть вопросы:
- А выполняет ли программа все предъявленные требования?
- А выполняет ли программа ТОЛЬКО то, что продиктовано требованиями?
Ответ на эти вопросы как раз и дает динамический анализ исполнения программы (не только он, конечно, но сейчас речь именно о нем).
Хорошо написанная программа делает только то, что должна и не делает того, что не должна. Соответственно, в идеальном случае мы выполняем действия из списка выше, т.е. готовим тестовые вектора на основе требований (что мы хотим, чтобы ПО делало), добавляем код, который будет отмечать прохождение контрольных точек в программе (инструментируем), прогоняем тесты и собираем трассы, анализируем. Тут есть несколько вариантов развития событий:
- Весь код, который мы инструментировали, исполнился хотя бы раз — 100% покрытие. Мы молодцы — мы написали хороший код и правильно собрали набор тестовых векторов для проверки;
- Не весь код покрылся. Тут тоже возможны варианты:
- Мы собрали плохой набор тестовых данных — не учли какие-то нюансы дизайна программы (воплощения требований программистом);
- Мы плохо написали программу — в ней есть «мертвый код» — инструкции, которые никогда не будут выполнены процессором ввиду ошибок программиста. Например: uint a = 0;
if (a == 0) <
a++;
if (a > 0) //do this
> else <
//do that
>
>. Код «do that» никогда не будет выполнен, он избыточен;
К слову, случай, когда мы все сделали правильно, а покрытие все равно не 100%, довольно редко встречается при сборе покрытия непосредственно для высокоуровневого (в нашем примере для языка С) кода. В данном случае мы оцениваем то, что написал человек и, исключив человеческие ошибки, вполне можно добиться заветных 100%. Но в случае, когда нужно доказать, что все покрывается на уровне исполняемого кода, все становится намного сложнее. Потому что он (исполняемый код) — только косвенно дело рук человеческих.
Дальше я приведу ряд упрощенных примеров, в основе которых реальные ситуации, встреченные в ходе анализа одного довольно крупного программного продукта с кучей легаси-кода.
Здравствуйте, я — ваш компилятор.
Редко, когда мы собираем программу, избегая возможностей современных компиляторов по оптимизации написанного нами высокоуровневого кода. Различных вариантов того, как компилятор модифицирует написанное человеком — превеликое множество. Все эти модификации как правило направлены на ускорение и уменьшение размеров результирующего исполняемого кода. Однако эти положительные моменты могут иногда существенно затруднить понимание того, как работает программа.
Давайте рассмотрим вот такой вроде-бы тривиальный случай:
#include #include volatile int v; int foo(int arg) < int i, rc; for (i = 0; i < arg; i++) < printf("Got PID %d!\n", getpid()); >printf("SKIPPED"); return arg; > int main(void)gcc -O2 main.c -o tst_app
Функция foo(), будет иметь непокрытый код (см фиг. 1).

Переход 34 -> 61 (номера строк) не покрыт. Давайте разберемся, откуда он вообще взялся.
Строка 30 ассемблерного кода «movl 16(%esp), %esi» помещает значение аргумента функции (arg) в регистр ESI и в строке 33 проверяет его «testl %esi, %esi». Если значение меньше или равно 0, то происходит переход на метку .L2, расположенную за телом цикла. Но мы же ничего такого не писали, верно? Да, но компилятор добавил эту проверку, дабы избежать ненужного вхождения в цикл при нулевом значении аргумента функции. Теперь для того, чтобы получить 100% покрытия, нам нужно добавить тестовый вектор, который вызовет foo() с 0.
Следующий пример показывает, насколько болезненными могут быть «мелкие» ошибки в дизайне, допущенные программистом. Например, неверный выбор типа для переменной.
volatile int a_signed_value; // Counter, valid values 0…10K. int main(void) < int ret_val = -(a_signed_value / 4096); return ret_val; >Вроде все линейно. Попробуете сами угадать что тут не покроется и найти причину?

Компилятор стремится привести операцию деления на кратное 2 число к операции битового сдвига. Разумно. Но проведение такой операции несколько отличается для отрицательных и положительных чисел, поэтому для случая, когда у числа есть знак, появляется дополнительный код (17 строка на графе).
Дополнительное условие, которое, в случае если переменная используется для хранения натуральных чисел (и нуля) никогда не покроется, если не дать заведомо невалидные входные значения. Конечно, это ошибка программиста, некорректно использовавшего знаковый тип для переменной, пропущенная на ревью, но бывает, что такие вещи просачиваются даже в самый проверенный код.Компилятор создает код, который должен обслуживать любое развитие событий в программе, поэтому часто он создает пути, которые не всегда можно предположить на первый взгляд (однако логичные при детальном рассмотрении).
Скрытая проблема в том, что то, что кажется хорошо продуманным и правильным, скажем, на С, на ассемблере может потребовать дополнительных объяснений.
Например, есть вот такая конструкция:
На вход этой функции при тестировании подавали следующие значения: 1, 2, 3, 4, 19, 20, 1000. В этом случае покрытие ассемблерного кода может быть следующим:

Эквивалентный код выглядит вот так:
if (com == 3) goto L3;
if (com > 3) goto L4;
if (com == 1) goto L5;
if (com != 2) goto L2;
…
if (com == 4) goto L7;
if (com – 19 L2:
seterr();Таким образом, код, который обслуживает дефолтный кейс считает, что значения могут лежать как выше, так и ниже диапазона валидных значений switch(). Если входные значения подобного кода могут быть заданы непосредственно, то это проблема решается расширением набора тестов, однако иногда такие конструкции используют входные значения, которые возвращаются другими функциями, ограниченными по набору возвращаемых значений, что приводит к необходимости все это объяснять в анализе.
Вы конечно можете возразить, что приведенные выше примеры — это случай, когда дали писать код интернам и вообще такого в реальной жизни не бывает. Все, кто пишет для embedded, а тем более для ответственного embedded, таких ошибок никогда не делают. Это не так. Люди есть люди.
К счастью, приведенные выше примеры не содержат никаких критических проблем для приложения, в котором они используются. И мы с чистой совестью можем написать, что непокрытые участки являются не более чем занятными курьёзами или артефактами компилятора.
Однако, и это тоже не всегда так. Поэтому иногда требуется детальный анализ покрытия, и, как я надеюсь дал понять выше, покрытие, собранное для ассемблерного кода, зачастую может существенно отличаться от того, что можно ожидать от покрытия, собранного для высокоуровневого языка.
Иллюстративный материал подготовлен с помощью gcc (GCC) 7.1.0 (примеры собраны с -O2), и небольшого приложения на питоне созданного для инструментирования С кода, о котором я расскажу в следующей статье.
Проверяем код динамического анализатора Valgrind с помощью статического анализатора

Сразу скажу, что статья пишется вовсе не для того, чтобы показать, что статический анализ работает лучше, чем динамический. Такое утверждение будет неверным, так же, как и обратное. Инструменты статического и динамического анализа дополняют друг друга, а не конкурируют между собой. У тех, и у тех есть сильные и слабые стороны. Некоторые ошибки не могут обнаруживать динамические анализаторы, а некоторые — не могут найти статические. Поэтому, следует отнестись к этой заметке просто, как к очередной демонстрации возможностей PVS-Studio, а не как к сравнению двух методологий.
Методологии динамического и статического анализа кода
Исходный код программы содержит подсказки, которые помогают выявить ошибки. Рассмотрим простой пример:
char *str = foo(); if (str == '\0')Странно сравнивать указатель не с nullptr, NULL или хотя бы с 0, а именно с символьным литералом ‘\0’. Исходя из этой странности, статический анализатор кода может предположить, что на самом деле хотели проверить не то, что указатель равен 0, а то, что строка пустая. Т.е. хотели проверить, что в начале строки располагается терминальный ноль, но случайно забыли разыменовать указатель. Скорее всего окажется, что это действительно ошибка, и правильный код должен быть таким:
char *str = foo(); if (*str == '\0')При компиляции подобная информация теряется, и динамический анализатор не способен выявить эту ошибку. С точки зрения динамического анализатора, указатель проверяется на равенство NULL — беспокоиться здесь не о чем.
Ещё одна слабость динамических анализаторов заключается в необходимости выполнить код, который содержит ошибку. А для многих участков кода сделать это бывает очень непросто. Поясню на примере кода, взятого из реального приложения:
ADOConnection* piTmpConnection = NULL; hr = CoCreateInstance( CLSID_DataLinks, NULL, CLSCTX_INPROC_SERVER, IID_IDataSourceLocator, (void**)&dlPrompt ); if( FAILED( hr ) ) < piTmpConnection->Release(); dlPrompt->Release( ); return connstr; >Если функция CoCreateInstance отработала с ошибкой, то произойдёт разыменование нулевого указателя piTmpConnection. На самом деле, здесь строчка piTmpConnection->Release(); просто лишняя, так как ещё никакое соединение не создавалось.
Выявить такую ситуацию с помощью динамического анализатора проблематично, так как надо эмулировать ситуацию, когда функция CoCreateInstance возвращает статус ошибки. Сделать это непросто.
Чисто теоретически, статический анализатор обладает информацией о коде, а значит способен находить больше ошибок, чем динамический анализатор. На практике, возможности статических анализаторов ограничены объемом доступной памяти и приемлемым временем работы. Другими словами, статический анализатор может рассмотреть, как будет работать код при всех возможных вариантах входных данных. Но делать он это будет 150 лет на кластере, где вдобавок установлен невероятный объём памяти.
В результате, на практике статические анализаторы не могут выявить многие типы ошибок. Например, они не замечают утечки, если указатель передастся между многими функциями. В свою очередь, динамические анализаторы отлично справляются с такими задачами, в независимости от сложности кода.
Результаты проверки
Мы регулярно проверяем различные проекты с целью популяризации методологии статического анализа кода, и я не мог пройти мимо такого проекта, как Valgrind. Найти в нем ошибки – это, своего рода, вызов. Это качественный, оттестированный проект, который вдобавок проверяется анализатором Coverity. Да и вообще, я уверен, что этот код проверялся энтузиастами разнообразнейшими инструментами. Так что, даже найти несколько ошибок — это большой успех.
Давайте посмотрим, что нашел интересного анализатор PVS-Studio в коде проекта Valgrind.
static void lk_fini(Int exitcode) < . VG_(umsg)(" taken: %'llu (%.0f%%)\n", taken_Jccs, taken_Jccs * 100.0 / total_Jccs ?: 1); . >Предупреждение PVS-Studio: V502 Perhaps the ‘?:’ operator works in a different way than it was expected. The ‘?:’ operator has a lower priority than the ‘/’ operator. lk_main.c 1014
Оператор ?: крайне коварен, и его надо использовать очень аккуратно. Подробнее я рассуждал на эту тему в 4 главе своей небольшой книги, куда я рекомендую заглянуть. Рассмотрим, чем этот код подозрителен.
Мне кажется, программист хотел защититься от деления на ноль. Поэтому, если переменная total_Jccs равна 0, то деление должно осуществляться на 1. Планировалось, что код будет работать так:
taken_Jccs * 100.0 / (total_Jccs ?: 1)Однако, приоритет оператора ?: ниже, чем у операторов умножения и деления. Поэтому, выражение вычисляется так:
(taken_Jccs * 100.0 / total_Jccs) ?: 1Впрочем, возможно код работает именно так, как и задумано. Если это так, всё равно, лучше добавить скобки, чтобы другие программисты не гадали в дальнейшем, есть здесь ошибка или нет.
static Bool doHelperCall (. )
Предупреждение PVS-Studio: V502 Perhaps the ‘?:’ operator works in a different way than it was expected. The ‘?:’ operator has a lower priority than the ‘==’ operator. host_arm_isel.c 795
Интересный случай. Оператор ?: используется неправильно, но код при этом корректен.
Задумывалось, что проверка должна работать так:
nVECRETs == ((retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0)Но работает это так:
(nVECRETs == (retTy == Ity_V128 || retTy == Ity_V256)) ? 1 : 0Самое забавное, что если присмотреться, то видно, что эти проверки эквивалентны. Результат будет один и тот же.
Аналогичные проверки находятся здесь:
- V502 Perhaps the ‘?:’ operator works in a different way than it was expected. The ‘?:’ operator has a lower priority than the ‘==’ operator. host_arm64_isel.c 737
- V502 Perhaps the ‘?:’ operator works in a different way than it was expected. The ‘?:’ operator has a lower priority than the ‘==’ operator. host_mips_isel.c 611
typedef ULong DiOffT; typedef struct < Bool fromC; DiOffT off; SizeT size; SizeT used; UChar data[]; >CEnt; static Bool is_sane_CEnt (. ) < . CEnt* ce = img->ces[i]; . if (!(ce->size == CACHE_ENTRY_SIZE)) goto fail; if (!(ce->off >= 0)) goto fail; // off + ce->used real_size)) goto fail; . >Предупреждение PVS-Studio: V547 Expression ‘ce->off >= 0’ is always true. Unsigned type value is always >= 0. image.c 147
Член off является переменной беззнакового типа, а значит он всегда больше или равен нулю. Таким образом, условие (!(ce->off >= 0)) всегда ложно.
static void sdel_Counts ( Counts* cts )
Предупреждение PVS-Studio: V597 The compiler could delete the ‘memset’ function call, which is used to flush ‘cts’ object. The memset_s() function should be used to erase the private data. cg_merge.c 324
Видимо, для упрощения поиска ошибок в самом Valgrind, память перед освобождением заполняется нулями. Однако, в release-версии компилятор, скорее всего, удалит вызов функции memset, так как буфер больше никак не используется до вызова функции free.
Аналогичные места, где память может не обнуляться:
- V597 The compiler could delete the ‘memset’ function call, which is used to flush ‘ffn’ object. The memset_s() function should be used to erase the private data. cg_merge.c 263
- V597 The compiler could delete the ‘memset’ function call, which is used to flush ‘cts’ object. The memset_s() function should be used to erase the private data. cg_merge.c 332
- V597 The compiler could delete the ‘memset’ function call, which is used to flush ‘cpf’ object. The memset_s() function should be used to erase the private data. cg_merge.c 394
static Bool dis_AdvSIMD_scalar_shift_by_imm(DisResult* dres, UInt insn) < . ULong nmask = (ULong)(((Long)0x8000000000000000ULL) >> (sh-1)); . >Предупреждение PVS-Studio: V610 Unspecified behavior. Check the shift operator ‘>>’. The left operand ‘((Long) 0x8000000000000000ULL)’ is negative. guest_arm64_toIR.c 9428
Если сдвигаемый вправо операнд имеет отрицательное значение, результирующее значение зависит от реализации (implementation-defined). Таким образом, мы имеем дело с опасным кодом.
Теперь рассмотрим ситуацию, когда разыменование указателя находится до его проверки на равенство NULL:
PRE(xsm_op) < struct vki_xen_flask_op *op = (struct vki_xen_flask_op *)ARG1; PRINT("__HYPERVISOR_xsm_op ( %u )", op->cmd); //Предупреждение PVS-Studio: V595 The 'op' pointer was utilized before it was verified against nullptr. Check lines: 350, 360. syswrap-xen.c 350
- V595 The 'sysctl' pointer was utilized before it was verified against nullptr. Check lines: 568, 578. syswrap-xen.c 568
- V595 The 'domctl' pointer was utilized before it was verified against nullptr. Check lines: 710, 722. syswrap-xen.c 710
Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) < . if (inrw && sdynbss_present) < vg_assert(di->sbss_present); sdynbss_present = False; vg_assert(di->sbss_svma + di->sbss_size == svma); di->sbss_size += size; . > else // sbss_present) < di->sbss_present = True; di->sbss_svma = svma; di->sbss_avma = svma + inrw->bias; . >Предупреждение PVS-Studio: V705 It is possible that 'else' block was forgotten or commented out, thus altering the program's operation logics. readelf.c 2231
Ключевое слово else выглядит в этом коде крайне подозрительно. Код не выравнен в соответствии с логикой его работы. Вдобавок, после else следует пустая строка. Это заставляет предположить, что перед нами последствия неудачного рефакторинга кода и данный else является лишним.
static Bool doHelperCallWithArgsOnStack (. ) < . if (guard) < if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1 && guard->Iex.Const.con->Ico.U1 == True) < /* unconditional -- do nothing */ >else < goto no_match; //ATC cc = iselCondCode( env, guard ); >> . >Предупреждение PVS-Studio: V779 Unreachable code detected. It is possible that an error is present. host_arm_isel.c 461
cc = iselCondCode( env, guard );никогда не выполняется:
void reset_valgrind_sink(const char *info) < if (VG_(log_output_sink).fd != initial_valgrind_sink.fd && initial_valgrind_sink_saved) < VG_(log_output_sink).fd = initial_valgrind_sink.fd; VG_(umsg) ("Reset valgrind output to log (%s)\n", (info = NULL ? "" : info)); >>Предупреждение PVS-Studio: V547 Expression '((void *) 0)' is always false. server.c 110
Предупреждение анализатора выглядит странно и требует пояснения.
Нас интересует следующее выражение:
(info = NULL ? "" : info))Макрос NULL разворачивается в ((void *) 0) и получается:
(info = ((void *) 0) ? "" : info))Приоритет оператора ?: выше чем у оператора =, поэтому вычисления происходят следующим образом:
(info = (((void *) 0) ? "" : info)))Согласитесь, что условие ((void *) 0) для оператора ?: смотрится странным, о чем и предупреждает анализатор PVS-Studio. По всей видимости, мы имеем дело с опечаткой, и код должен был быть таким:
(info == NULL ? "" : info))И последний на сегодня фрагмент кода:
void genReload_TILEGX ( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg, Int offsetB ) < TILEGXAMode *am; vassert(!hregIsVirtual(rreg)); am = TILEGXAMode_IR(offsetB, TILEGXGuestStatePointer()); switch (hregClass(rreg)) < case HRcInt64: *i1 = TILEGXInstr_Load(8, rreg, am); break; case HRcInt32: *i1 = TILEGXInstr_Load(4, rreg, am); break; default: ppHRegClass(hregClass(rreg)); vpanic("genReload_TILEGX: unimplemented regclass"); break; >>Предупреждение PVS-Studio: V751 Parameter 'i2' is not used inside function body. host_tilegx_defs.c 1223
Думаю, здесь забыли записать NULL по адресу i2, как это сделано в других аналогичных функциях:
*i1 = *i2 = NULL;Аналогичная ошибка находится здесь:
V751 Parameter 'i2' is not used inside function body. host_mips_defs.c 2000
Заключение
Спасибо всем за внимание. Попробуйте наш статический анализатор кода PVS-Studio для Linux.
- Скачать: PVS-Studio for Linux
- Получить временный лицензионный ключ: напишите нам.
- Инструкция: Как запустить PVS-Studio в Linux.

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. Checking the code of Valgrind dynamic analyzer by a static analyzer
Прочитали статью и есть вопрос?
Часто к нашим статьям задают одни и те же вопросы. Ответы на них мы собрали здесь: Ответы на вопросы читателей статей про PVS-Studio, версия 2015. Пожалуйста, ознакомьтесь со списком.
Проверка орфографии
Выполнять проверку орфографии можно в отдельном документе или во всех открытых материалах. InCopy выделяет цветом слова с ошибками и неизвестные слова, повторяющиеся слова (например, «и и»), слова и предложения, начинающиеся не с прописной буквы. При проверке орфографии InCopy проверяет все содержимое XML и развернутые встроенные примечания.
При проверке орфографии InCopy использует словари для языков, которые назначены тексту в документе. InCopy использует словари для поиска близких слов как при проверке орфографии, так и при расстановке переносов. Каждый словарь содержит сотни тысяч слов со стандартной разбивкой по слогам.
Для автономных материалов (материалов, не связанных с макетом InDesign) можно настроить языковые словари, что позволяет их корректно распознавать и обрабатывать. Например, при запуске проверки орфографии (меню «Редактирование» > «Орфография» > «Проверка орфографии») можно нажать кнопку «Добавить» и задать нужные параметры.
Установка параметров проверки орфографии
Выберите меню «Редактирование» > «Установки» > «Орфография» (для Windows) или «InCopy» > «Установки» > «Орфография» (для Mac OS).
Выполните одно из следующих действий:
- Выберите параметр «Слова с ошибками» для поиска слов, которые отсутствуют в языковом словаре.
- Выберите параметр «Повторяющиеся слова» для поиска дублирующихся слов (например, «для для»).
- Выберите параметр «Слова не с прописных» для поиска слов, которые в словаре начинаются с прописных букв (например, «германия», а в словаре — «Германия»).
- Выберите параметр «Предложения не с прописных» для поиска слов, начинающихся не с прописной буквы, которые следуют за точками, восклицательными знаками и вопросительными знаками.
Выберите параметр «Включить динамическую проверку орфографии», чтобы в процессе ввода подчеркивались слова, которые, возможно, содержат ошибки.
Укажите цвет подчеркивания слов, содержащих ошибки (не найденных в пользовательских словарях), повторяющихся слов (например, «для для»), слов, начинающихся не с прописной буквы (например, «нигерия» вместо «Нигерия»), и предложений, начинающихся не с прописной буквы (если в начале предложения отсутствует прописная буква).
Примечание.
Для проверки орфографии в примечаниях убедитесь, что в разделе установок «Примечания» задан параметр «Учитывать содержимое примечаний при проверке орфографии». Для проверки орфографии в удаленном тексте убедитесь, что в параметрах «Отслеживание изменений» выбрано «Учитывать удаленный текст при проверке правописания».
Проверка орфографии
Если документ содержит текст на иностранном языке, выделите его, затем в меню «Язык» на палитре «Символ» выберите другой язык.
Выберите меню «Редактирование» > «Орфография» > «Проверка орфографии».
Начинается проверка орфографии.
Примечание.Команда «Проверка орфографии» не проверяет свернутые материалы в файле, содержащем несколько материалов. Однако если выбрать «Заменить все» или «Игнорировать все», то обработке будут подвергнуты также все свернутые материалы и таблицы.
Если необходимо изменить область проверки орфографии, выполните одно из следующих действий, а затем нажмите кнопку «Начать».
- Выберите «Документ», чтобы проверить весь документ. Выберите все документы , чтобы проверить орфографию в открытых документах.
- Выберите «Материал», чтобы проверить весь текст внутри текущего выделенного фрейма и других связанных с ним фреймах, включая также вытесненный текст. Выберите «Материалы», чтобы проверить материалы во всех выделенных фреймах.
- Выберите «До конца материала», чтобы выполнить проверку от позиции точки ввода.
- Выберите «Выделенный фрагмент», чтобы проверить только выделенный текст. Этот параметр доступен только в том случае, если выделен текст.
При обнаружении незнакомых слов, слов с орфографическими ошибками и других возможных ошибок выберите один из следующих вариантов.
- Нажмите кнопку «Пропустить», чтобы продолжить проверку орфографии, не изменяя слово, выделенное подсветкой. Нажмите кнопку «Игнорировать все», чтобы пропустить все вхождения выделенного слова до следующего перезапуска InCopy.
- Выберите слово из списка «Предлагаемые исправления» или введите правильный вариант написания слова в поле «Заменить на», а затем нажмите кнопку «Заменить», чтобы исправить только данное вхождение слова с ошибкой. Можно также нажать кнопку «Заменить все», чтобы заменить все вхождения слова с ошибкой в этом документе.
- Чтобы добавить слово к словарю, выберите словарь в меню «Добавить в», а затем нажмите кнопку «Добавить».
- Нажмите кнопку «Словарь», чтобы вывести на экран диалоговое окно «Словарь», которое позволяет указать целевые словарь и язык, а также задать переносы для добавляемого слова. Если требуется добавить слово для всех языков, выберите «Все языки» в меню «Язык». Нажмите кнопку «Добавить».
Исправление орфографических ошибок в процессе ввода текста
Режим «Автокоррекция» позволяет в процессе ввода обеспечить замену ошибочного преобразования букв в прописные и типичных ошибок ввода. Чтобы обеспечить работу в режиме «Автокоррекция», необходимо создать список слов, в которых обычно возникают орфографические ошибки, а затем связать их с правильными вариантами написания.
Выберите меню «Редактирование» > «Установки» > «Автокоррекция» (для Windows) или «InCopy» > «Установки» > «Автокоррекция» (для Mac OS).
Выберите параметр «Включить автокоррекцию». Быстро включить или выключить эту функцию можно также через меню «Редактирование» > «Орфография» > «Автокоррекция».
В меню «Язык» выберите язык, для которого применяется автокоррекция.
Чтобы исправить ошибки преобразования букв в прописные (например, «германия» вместо «Германия»), выберите параметр «Исправлять ошибки капитализации». Добавлять в список автоисправлений слова с буквами, ошибочно преобразованными в прописные, не требуется.
Чтобы добавить слово, в котором часто возникают орфографические ошибки, нажмите кнопку «Добавить», введите слово с орфографической ошибкой (например, «дял»), исправление (в данном примере «для»), а затем нажмите кнопку «ОК».
После окончания добавления слов нажмите кнопку «ОК».
При вводе ошибочного слова, если оно найдено в списке, произойдет его автоматическая коррекция.
Чтобы удалить слово, добавленное в список автоисправлений, выберите его в списке и нажмите «Удалить». Чтобы отредактировать слово из списка автоисправлений, выберите его, нажмите «Редактировать», введите новый вариант и нажмите «OK».
Использование динамической проверки орфографии
Динамическая проверка орфографии позволяет исправлять орфографические ошибки через контекстное меню. После проверки по языковому словарю все слова, которые могут содержать орфографические ошибки, будут подчеркнуты. Если текст содержит слова на различных языках, выделите текст и назначьте ему правильный язык.
Чтобы включить динамическую проверку орфографии, выберите меню «Редактирование» > «Орфография» > «Динамическая проверка орфографии».
Слова в документе, в которых, возможно, имеются ошибки, выделены подчеркиванием.
Нажмите подчеркнутое слово правой кнопкой (Windows) или при нажатой клавише Control (Mac OS) и выполните одно из следующих действий:
- Выберите предложенное исправление. Если слово повторяется или требует преобразования в прописные буквы, то можно выбрать «Удалить повторяющееся слово [слово]» или «Набрать прописными [слово]».
- Выбрать «Добавить [слово] в словарь пользователя». В результате этого произойдет автоматическое добавление слова к текущему словарю без открытия диалогового окна «Словарь». Слово в тексте не изменяется.
- Выберите «Словарь». При этом откроется диалоговое окно «Словарь», в котором можно выбрать целевой словарь, расставить переносы и указать язык. Если требуется добавить слово для всех языков, выберите «Все языки» в меню «Язык» и нажмите «Добавить». Слово добавляется к выбранному словарю, а в тексте не изменяется.
- Выберите «Игнорировать все», чтобы пропустить вхождения этого слова во всех документах. После перезапуска InCopy это слово снова будет помечено как ошибочное.
Примечание.
Если «Игнорировать все» выбрано по ошибке, то в диалоговом окне «Словарь» в меню «Список словарей» выберите пункт «Проигнорированные слова» и удалите это слово из списка.
Словари для расстановки переносов и проверки орфографии
В InCopy для большинства языков используются словари проверки орфографии и расстановки переносов. Каждый из словарей можно пополнять и настраивать. Для текста можно назначать различные языки; при этом при проверке орфографии и расстановке переносов в InCopy используется соответствующий словарь. Вы можете позволяет создавать дополнительные пользовательские словари, импортировать и экспортировать словарные статьи, сохраненные в виде простых текстовых файлов.
При пополнении словарей на самом деле создаются списки добавленных слов (слов, которые прежде отсутствовали в словаре) и удаленных слов (словарных слов, которые были помечены как ошибочные). В диалоговом окне «Словарь» можно просматривать и редактировать добавленные, удаленные и проигнорированные слова (слова, которые игнорируются на протяжении текущего сеанса работы, поскольку для них была нажата кнопка «Игнорировать все»). Можно добавить слова, применимые для всех языков, что особенно полезно при вводе фамилий, названий улиц и других слов, не требующих перевода.
Примечание.
Если возникла необходимость использовать языковые словари из прежней версии InDesign или InCopy, при помощи системной команды «Поиск» следует найти файлы пользовательских словарей (.udc) и добавить их в список установок «Словарь».
Место хранения словарных пар
По умолчанию особые случаи переноса и орфографии содержатся в файлах словарей пользователей, которые хранятся отдельно от документа — на компьютере с установленной программой InCopy (имена файлов словарей имеют расширения .clam или .not). Однако списки особых случаев можно хранить также внутри документов InCopy. Кроме того, можно хранить списки слов во внешних пользовательских словарях, в документах или одновременно и в словарях, и в документах. О расположении существующих словарей можно узнать из установок «Словаря».
Хранение правил переноса и особых случаев правописания внутри файла документа облегчает согласованную работу с ним при перемещении документа с одного компьютера на другой. В разделе установок «Словарь» можно перенести содержимое пользовательского словаря в документ. Расположением особых случаев правописания также можно управлять с помощью диалогового окна «Создать папку контейнера». С другой стороны, хранение перечня особых случаев вне документа упрощает использование перечня со множеством разных документов.
Примечание.
Если пользовательский словарь объединяется с перечнем исключений, в документ включается весь словарь целиком, вне зависимости от числа использованных слов, что увеличивает размер файла документа.
Привязка языка к тексту
Чтобы привязать язык к выделенному тексту, можно воспользоваться меню «Язык» на панели «Символ». Кроме того, всему документу или всем создаваемым документам можно присвоить язык по умолчанию В InCopy реализована функция блокировки, которая не позволяет изменять языковые настройки текста на языке стран Азии, если этот текст выделен и в меню «Язык» выбраны настройки для другого языка (см. раздел Назначение языка для текста).
Чтобы привязать язык к выделенному тексту, можно воспользоваться меню «Язык» на панели «Управление» или на палитре «Символ». Кроме того, всему документу или всем создаваемым документам можно присвоить язык по умолчанию (см. раздел Назначение языка для текста).
Списки слов-исключений
Некоторые слова можно исключить из числа проверяемых. Например, общеизвестное слово «велосипед» требуется использовать в измененном написании — в каком-то одном документе или как наименование компании; такое слово просто вносится в перечень слов-исключений и в результате перестает мешать проверке орфографии. В InCopy можно вести отдельный перечень добавленных и удаленных слов для каждого установленного языка.
Создание и добавление пользовательских словарей
Вы можете создать собственный пользовательский словарь, подключить словари из предыдущих версий InDesign и InCopy, подключить словари, присланные другими пользователями, или загрузить словарь рабочей группы с сервера. Подключенный словарь будет использоваться для всех документов InCopy.
Выберите меню «Редактирование» > «Установки» > «Словарь» (для Windows) или «InCopy» > «Установки» > «Словарь» (для Mac OS).
Выберите язык, который требуется привязать к словарю, в меню «Язык».
Выполните одно из следующих действий:- Чтобы создать новый словарь, нажмите значок «Новый словарь пользователя», расположенный
под меню «Язык». Задайте имя и папку для пользовательского словаря (включая расширение .udc), после чего нажмите кнопку «Сохранить». - Чтобы подключить готовый словарь, нажмите значок «Добавить словарь пользователя»
, выберите файл пользовательского словаря с расширением .udc или .not, а затем нажмите кнопку «Открыть».
Примечание.
Если файл словаря найти не получается, можно прибегнуть к системной команде «Поиск» и найти все файлы с расширением .udc (поиск по *.udc), запомнить путь и затем повторить попытку подключения.
Словарь после подключения появляется в списке, расположенном под меню «Язык». Можно добавлять слова в словарь во время проверки орфографии или через диалоговое окно «Словарь».
Задание языкового словаря по умолчанию для текущего документа
Можно изменить словарь языка, используемого по умолчанию, для документа или для всех новых создаваемых документов. Изменение для документа словаря по умолчанию никак не влияет на уже созданный текст или на текст, который только что вводился в текстовый фрейм.
Примечание.
Чтобы задать определенный словарь как атрибут определенного стиля, следует воспользоваться палитрой «Стиль символа» или «Стиль абзаца». Меню «Язык» находится в разделе «Дополнительные атрибуты символов».
Откройте документ.
Выберите на панели «Инструменты» инструмент «Выделение» и убедитесь, что в документе не выбран ни один элемент.
Выберите меню «Текст» > «Символ».
На палитре «Символ» в раскрывающемся меню «Язык» выберите нужный словарь. Если на палитре «Символ» отсутствует нужный язык, выберите «Показать параметры» и выберите язык из списка.
Выбор языкового словаря по умолчанию для всех новых документов
Запустите InCopy, но не открывайте документ.
Выберите меню «Текст» > «Символ».На палитре «Символ» в раскрывающемся меню «Язык» выберите нужный словарь. Если на палитре «Символ» отсутствует нужный язык, выберите «Показать параметры» и выберите язык из списка.
Удаление, повторное связывание и переупорядочение словарей пользователя
Выберите меню «Редактирование» > «Установки» > «Словарь» (для Windows) или «InCopy» > «Установки» > «Словарь» (для Mac OS).
В меню «Язык» выберите язык, к которому относится словарь.
Выполните одно из следующих действий:- Чтобы удалить словарь из списка, выберите его и нажмите значок «Удалить словарь пользователя»
. Для каждого из языков должен существовать хотя бы один словарь. - Если языковой словарь помечен значком вопросительного знака, выделите словарь, нажмите значок «Повторно связать со словарем пользователя»
, после чего найдите и откройте пользовательский словарь. - Чтобы изменить порядок следования пользовательских словарей, перетащите словари в нужное местоположение. Порядок следования словарей в перечне соответствует порядку, в котором программа сверяется с каждым из них.
Добавление слов в словари
Если при проверке правописания InDesign показывает в диалоговом окне «Проверка орфографии» обнаруженное неизвестное слово, укажите в меню «Добавить в» нужный словарь, а затем нажмите кнопку «Добавить». Кроме того, в диалоговом окне «Словарь» можно указать целевые словарь и язык, а также способ добавления слов в список исключенных.
Словами из самостоятельных материалов (материалов, которые не связаны с макетом InDesign) можно пополнять языковые словари. Пополнение словарей гарантирует, что любые редкие слова, которые используются в работе, программе будут известны и станут правильно обрабатываться.
Выберите «Редактирование» > «Орфография» > «Словарь пользователя».
В меню «Язык» укажите язык. Для каждого языка существует хотя бы один словарь. Если требуется добавить слово сразу во все словари, выберите «Все словари».
В меню «Назначение» укажите словарь, в который следует занести слово. Меню «Назначение» позволяет сохранить изменения, внесенные в любой из внешних пользовательских словарей или открытый документ.
В меню «Список словарей» выберите пункт «Добавленные слова».
В поле «Слово» введите новое слово или измените указанное, слово будет внесено в список.Чтобы отобразить определенные по умолчанию варианты переносов для нового слова, нажмите «Переносы». Символом тильды (~) обозначены возможные места переносов.
Если предлагаемые правила переноса не годятся, укажите желательные правила переноса для этого слова, руководствуясь следующими указаниями.
- Одним символом тильды (~) обозначают наилучшие из возможных точки переноса (или единственную такую точку) для этого слова.
- Двумя символами тильды (~~) обозначают менее желательные варианты.
- Три символа тильды (~~~) обозначают нежелательную, но все же приемлемую точку переноса.
- Если переносы в слове недопустимы, символ тильды должен стоять перед первой буквой слова.
Примечание.
Включить в слово сам значок тильды, понимаемый как часть слова, можно, введя перед тильдой обратную косую черту (\~).
Нажмите кнопку «Добавить», а затем нажмите кнопку «Готово». Слово будет добавлено в текущий список «Список словарей».
Примечание.
Не следует забывать, что точки переноса не отменяют, а дополняют настройки переносов, заданные для документов. Как следствие, перенос все же может оказаться не в том месте, где ожидалось. Этими настройками можно управлять, выбрав в меню палитры «Абзац» пункт «Переносы». См. раздел Расстановка переносов.
Удаление и редактирование слов в словарях
Выберите «Редактирование» > «Орфография» > «Словарь пользователя».
В меню «Язык» укажите язык.В меню «Назначение» укажите словарь, откуда следует удалить слово. Меню «Назначение» позволяет выбрать внешний пользовательский словарь или любой открытый документ.
В меню «Список словарей» выполните одно из следующих действий:
- Чтобы изменить список добавлений к выбранному перечню слов, выберите пункт «Добавленные слова».
- Чтобы изменить список слов, которые определяются как слова с ошибками, выберите пункт «Удаленные слова».
- Для изменения списка слов, игнорируемых в текущем сеансе InCopy, выберите «Проигнорированные слова». В этот список входят все слова, для которых была нажата кнопка «Игнорировать все».
Открыв список, отредактируйте слово или выберите слово и нажмите «Удалить».
Нажмите «Готово».Экспорт списка слов
Списки слов можно экспортировать в текстовый файл (.txt), а затем импортировать их в пользовательский словарь InCopy. Слова в текстовом файле следует отделять пробелом, символом табуляции или символом начала нового абзаца. Экспортируются только добавленные и удаленные слова, но не игнорируемые (последний список существует только в пределах текущего сеанса работы).
Выберите «Редактирование» > «Орфография» > «Словарь пользователя».
В меню «Язык» выберите язык, а затем в меню «Назначение» — словарь, который содержит список слов, которые следует экспортировать.
Нажмите «Экспортировать», чтобы указать имя и местоположение файла, а затем нажмите «Сохранить».
Список слов будет сохранен в текстовом файле. Данный список слов редактируется в любом текстовом редакторе, после чего его можно снова импортировать. Список слов можно также отправить коллегам, которые смогут импортировать его в собственные пользовательские словари.
Импорт списка слов
Выберите «Редактирование» > «Орфография» > «Словарь пользователя».
В меню «Язык» выберите язык, а затем в меню «Назначение» — словарь.Нажмите кнопку «Импортировать», укажите текстовый файл со списком особых случаев орфографии и нажмите кнопку «Открыть».
Изменение установок словаря
Используйте настройки словаря для определения настроек расстановки переносов и словарей проверки орфографии в InCopy. В InCopy для проверки орфографии и расстановки переносов в большинстве языков используются словари расстановки переносов. Если к программе добавлены плагины расстановки переносов и проверки орфографии производства другой компании, для каждого из установленных языков допустимо использовать другого поставщика.
Примечание.
Диалоговое окно «Установки словаря» не позволяет задать языковой словарь для проверки орфографии и расстановки переносов. Это диалоговое окно используется для указания плагинов расстановки переносов и проверки орфографии, используемых в InCopy для языков, установленных в поле «Язык». При использовании плагинов расстановки переносов и проверки орфографии из комплекта поставки, никаких параметров в диалоговом окне «Установки словаря» менять не нужно. Если в программе установлен плагин проверки орфографии или расстановки переносов от стороннего разработчика, он появляется отдельным пунктом в меню «Поставщик переносов» и «Поставщик орфографии» этого диалогового окна. Это позволяет выбрать плагин проверки орфографии или расстановки переносов от одного поставщика для одних языков и такие же плагины от другого поставщика для других языков.
Выберите меню «Редактирование» > «Установки» > «Словарь» (для Windows) или «InCopy» > «Установки» > «Словарь» (для Mac OS).
В меню «Язык» укажите язык, для которого требуется отредактировать настройки или сменить поставщика плагина расстановки переносов или проверки орфографии.
Создание, подключение и удаление пользовательских словарей (см. раздел Создание и добавление пользовательских словарей).
Если к программе подключен плагин расстановки переносов не от корпорации Adobe, выберите его в меню «Переносы».
Если к программе подключен плагин проверки орфографии стороннего производителя, выберите его в меню «Орфография».
В меню «Использовать при компоновке» в меню «Особые случаи переноса» выполните одно из следующих действий:
- Чтобы при верстке использовать переносы по особым правилам, список которых хранится во внешнем пользовательском словаре, выберите параметр «Словарь пользователя».
- Чтобы при верстке использовать переносы по особым правилам, список которых хранится в самом документе, выберите параметр «Документ».
- Чтобы при верстке использовать оба списка, выберите параметр «Словарь пользователя и документ». Это настройка используется по умолчанию.
Чтобы пополнить список, хранящийся в документе, списком исключений из внешнего пользовательского словаря, выберите параметр «Включать словарь пользователя в документ».
Примечание.
Если вы работаете с большим количеством партнеров или клиентов, следует отключить параметр «Включать словарь пользователя в документ». Например, если вы являетесь поставщиком услуг, вам вряд ли захочется пополнять собственный пользовательский словарь содержимым каждого нового файла заказчика.
Чтобы перекомпоновать все материалы после внесения каких-либо изменений, выберите параметр «В случае модификации перекомпоновывать все материалы». Если этот параметр включен, то в случае изменения параметра «Использовать при компоновке» (см. шаг 6) или при использовании команды «Словарь» для добавления или удаления слова материалы будут перекомпонованы. Перекомпоновка всех материалов, в зависимости от количества текста в документе, может занять некоторое время.
Нажмите кнопку «ОК».
Использование словарей в рабочей группе
Убедитесь, что на всех компьютерах рабочей группы установлены и подключены одни и те же доработанные пользовательские словари, чтобы вне зависимости от того, кто именно с ним работает, документ использовал одни и те же правила расстановки переносов и проверки орфографии. Следует либо проследить, чтобы каждый на своем компьютере подключил одни и те же словари, либо убедиться, что все используют один пользовательский словарь, расположенный на сетевом сервере.

Значок блокировки говорит о том, что словарь заблокирован и его можно использовать, но без права вносить изменения. Когда пользовательский словарь расположен на сервере, первый загрузивший его пользователь блокирует его файл и все последующие пользователи видят, что словарь заблокирован. Файлы также можно блокировать средствами операционной системы, которая делает их доступными только для чтения. Если словарь выкладывается для совместного доступа на сетевой сервер, логичным будет его заблокировать для всех рядовых пользователей, оставив право вносить новые слова только администратору.
Удостоверьтесь в том, что все члены рабочей группы используют доработанный пользовательский словарь, установленный на общем сетевом компьютере, а не словарь, встроенный в документ. И все же перед отправкой документа в другую организацию разумно дополнить документ пользовательским словарем
Если один доработанный пользовательский словарь не предоставлен для совместного доступа через общий сетевой компьютер, следует найти файлы пользовательских словарей и скопировать их на все оставшиеся компьютеры. О расположении существующих словарей можно узнать из раздела установок «Словарь».
Примечание.
После обновления пользовательского словаря на общем сетевом компьютере изменения в нем станут доступны персональным компьютерам только после перезагрузки InCopy или перекомпоновки всего текста, выполненной нажатием Ctrl+Alt+/ (Windows) или Command+Option+/ (Mac OS).
Словарь Дудена
Словарь Дудена теперь добавлен в InCopy. Можно использовать словарь Дудена для правильного переноса слов и проверки орфографии на немецком языке.
- Windows: «Редактирование» > «Установки» > «Словарь»
- macOS: «InCopy» > «Установки» > «Словарь»
- Немецкий: реформа 1996 г.
- Немецкий: реформа 2006 г.
- Немецкий: реформа 2006 г. (Австрия)
- Немецкий: швейцарский
- Немецкий: реформа 2006 г. (Швейцария)
Примечание.
Был добавлен Немецкий: реформа 2006 г. (Австрия) .

Выберите словарь «Дуден» в раскрывающихся списках «Переносы» и «Орфография», если он не выбран по умолчанию.
Статический и динамический анализ исходного кода
Демидов, П. Д. Статический и динамический анализ исходного кода / П. Д. Демидов. — Текст : непосредственный // Молодой ученый. — 2019. — № 2 (240). — С. 2-4. — URL: https://moluch.ru/archive/240/55456/ (дата обращения: 30.10.2023).
С сообщениями об уязвимостях веб-сайтов и утечках конфиденциальных данных, регулярно появляющимися в новостях, защита жизненного цикла разработки программного обеспечения становится особенно важной. Таким образом, предприятие должно тщательно выбирать правильные методы обеспечения безопасности. Статический и динамический анализ являются двумя наиболее популярными типами тестов безопасности кода. Перед внедрением, однако, предприятие, которое заботится о безопасности, должно точно изучить, как оба типа тестов могут помочь защитить жизненный цикл программного продукта. В конце концов, тестирование можно считать инвестицией, которую следует тщательно контролировать.
Статический идинамический анализ
Статический анализ выполняется в среде без времени выполнения. [1] Как правило, инструмент статического анализа проверяет программный код на предмет всех возможных режимов работы во время выполнения и выявляет недостатки проектирования, черные ходы и потенциально вредоносный код.
Статический анализ кода может помочь в процессе код-ревью благодаря:
- обнаружению областей в коде, которые необходимо реорганизовать и упростить;
- поиску областей кода, которые могут нуждаться в дополнительном тестировании или более глубоком рассмотрении;
- выявлению проблем проектирования, таких как цикломатическая сложность, и помощь в снижении сложности кода, улучшении удобства обслуживания;
- выявление потенциальных проблем с качеством программного обеспечения до его запуска в промышленную эксплуатацию.
Динамический анализ использует противоположный подход и выполняется во время работы программы. [2] Динамический тест будет контролировать системную память, функциональное поведение, время отклика и общую производительность системы. Этот метод схож со способом, которым злонамеренная третья сторона может взаимодействовать с приложением.
Динамический анализ может дать вам следующие показатели:
- потребляемые ресурсы — время выполнения программы в целом или ее модулей в отдельности, количество внешних запросов (например, к базе данных), количество используемой памяти и другие ресурсы;
- цикломатическая сложность, степень покрытия кода тестами и другие метрики программы;
- программные ошибки — деление на ноль, разыменование нулевого указателя, утечки памяти, состояние гонки
- уязвимости в программе.
Возникшие и развивавшиеся отдельно, статический и динамический анализ порой ошибочно воспринимаются как противоположные. Однако существует ряд сильных и слабых сторон, связанных с обоими подходами.
Сильные ислабые стороны статического идинамического анализа
Статический анализ с его видимостью в виде «белого ящика», безусловно, является более тщательным подходом и может также оказаться более экономичным с возможностью обнаружения ошибок на ранней стадии жизненного цикла разработки программного обеспечения. Например, если ошибка обнаружена на во время статического анализа — это может быть относительно дешево исправить. Если бы ошибка оказалась в системе, затраты увеличились бы. Статический анализ также может выявить будущие ошибки, которые не возникнут при динамическом тестировании. Динамический анализ, с другой стороны, способен выявлять тонкие недостатки или уязвимости, слишком сложные для одного лишь статического анализа, и также может быть более целесообразным методом тестирования. Динамический анализ, однако, обнаружит дефекты только в той части кода, которая фактически выполняется. Предприятие должно взвесить эти соображения с учетом сложности их собственной ситуации. Тип приложения, время и ресурсы компании являются одними из основных факторов. Уровень технического долга, который предприятие готово взять на себя, также может быть измерен. Определенное количество технического долга может быть взято на себя, если финансовые выгоды от победы над конкурентом на рынке перевешивают потенциальную экономию от более тщательно протестированного кода. Хотя и у статических, и у динамических тестов есть свои недостатки, предприятие не должно стоять перед выбором. В то время как статический анализ можно считать превосходным методом тестирования, это не обязательно означает, что он должен автоматически выбираться вместо динамического анализа в любой ситуации, когда возникает выбор.
Автоматизация анализа исходного кода
Хотя статический и динамический анализ можно выполнять вручную, они также могут быть автоматизированы. При грамотном использовании автоматизированные инструменты могут значительно повысить отдачу от инвестиций в тестирование. Инструменты автоматического тестирования являются идеальным вариантом в определенных ситуациях. Например, автоматизация может использоваться для проверки реакции системы на большое количество пользователей или для подтверждения того, что исправление ошибки работает должным образом. Она также помогает автоматизировать тесты, которые регулярно выполняются во время разработки продукта. Поскольку предприятие стремится обеспечить защищенность продукта во время его жизненного цикла, следует отметить, что панацея отсутствует. Ни статическое, ни динамическое тестирование сами по себе не могут обеспечить полную защиту. В идеале предприятие должно выполнять как статический, так и динамический анализ. Этот подход выиграет от синергетических отношений, существующих между статическим и динамическим тестированием. [3]
Заключение
С таким количеством современных устройств, поддерживающих веб-интеграцию, методы безопасного кодирования важны как никогда. Например, динамический анализ кода стал важным инструментом для демонстрации соответствия безопасности медицинских устройств требованиям FDA. Он обеспечивает эффективный анализ потенциальной угрозы и, в сочетании со статическим анализом, обеспечивает мощный обзор возможных уязвимостей.
- Статический анализ кода // Википедия. URL: https://ru.wikipedia.org/wiki/Статический_анализ_кода (дата обращения: 8.01.2019).
- Динамический анализ кода // Википедия. URL: https://ru.wikipedia.org/wiki/Динамический_анализ_кода (дата обращения: 8.01.2019).
- Макконнелл С. Совершенный код. Мастер-класс / Пер. с англ. — М.: Издательско-торговый дом «Русская редакция»; СПб.: Питер, 2005. — 896 стр.
Основные термины (генерируются автоматически): динамический анализ, статический анализ, динамическое тестирование, программное обеспечение, FDA, время выполнения, жизненный цикл, жизненный цикл разработки, предприятие, цикломатическая сложность.