Это довольно открытый вопрос, на который нет правильного ответа. Но как человек, работавший с несколькими статическими анализаторами, я укуслю и кратко объясню, что сложного в этом примере.
Проблема 1: Ложные срабатывания
Мы с вами знаем, что argv[1]
может быть произвольно длинной строкой. (Отчасти это знание получено из контекста вопроса о переполнении стека, в котором код обычно представлен без какого-либо контекста или предварительных предположений.) Но если статический анализатор сообщает о каждом strcpy
, где исходная строка не была известна (по статический анализатор!) иметь ограниченную длину, на практике он будет сообщать очень большое количество того, что большинство разработчиков сочло бы ложными срабатываниями (FP): неверные отчеты, которые они не хотят видеть.
Это связано с тем, что существует очень большое количество случаев, когда strcpy
используется правильно, но причина, по которой это правильно, выходит за рамки разумных возможностей анализатора и может вообще не присутствовать в исходном коде (например, «программа X — это всего лишь когда-либо вызываемая программой Y, которая никогда не передает аргументы длиннее 80 символов"). Для сравнения, только очень небольшая часть вызовов strcpy
(с аргументами, которые анализатор не может связать) ошибочны. Давайте будем великодушны и скажем, что 10% из них неверны — это все равно будет 90% FP, если мы сообщим их все, что намного превышает то, что большинство разработчиков потерпит.
Когда инструмент сообщает о слишком большом количестве FP, большинство разработчиков быстро перестают его использовать, после чего он бесполезен. Следовательно, большинство статических анализов предпочитают ограничивать то, что они сообщают, случаями, когда инструмент достаточно уверен, по крайней мере, по умолчанию.
Проблема 2: Межпроцедурный анализ
Даже для инструмента, который хочет сообщить об этом (как, по вашим словам, делает Cppcheck, когда strcpy
находится непосредственно в main
), второй проблемой является понимание того, что делает buffer_overflow
. Для статического анализатора нецелесообразно просто «встраивать» содержимое вызываемых объектов в вызывающие объекты с произвольной глубиной, потому что результирующий AST будет огромным, а количество путей — астрономическим. Следовательно, анализаторы обычно обобщают поведение вызываемого объекта. Точная форма этих сводок и алгоритмы, которые их вычисляют, являются предметом активных академических исследований и строго охраняемой коммерческой тайной.
Поведение strcpy
на самом деле довольно сложное по сравнению с тем, что может выразить типичная сводка функций. Здесь задействован размер, но этот размер получается путем проверки содержимого данных, на которые указывает один из указателей, в частности, местоположения первого NUL-байта. Затем этот размер влияет на то, что происходит с вещами, указываемыми обоими аргументами. Это много, чтобы закодировать сводку в общем и масштабируемом виде, поэтому большинство инструментов этого не делают. В результате инструмент имеет очень приблизительное представление о том, что делает buffer_overflow
, как правило, слишком грубое, чтобы позволить ему уверенно сообщить здесь о дефекте.
person
Scott McPeak
schedule
08.09.2019
strlen
, а затем зарезервировали память. Что, если я вызову вашу программу с аргументом длиной в два гигабайта? - person Damon   schedule 09.03.2019cppcheck
считаетstrcpy()
проблематичным, если я не прячу его в вопросе {{buffer_overflow()}}. Статический анализатор Clang специально имеет анализатор дляstrcpy
API. - person Chad   schedule 09.03.2019