STM32嵌入式存储器overflow/leak检测
STM32 embedded memory overflow/leak detection
我被咬了几次屁股,我会写一个超出范围的数组。我已经在一个特定的固件上工作了 2 年多,并且怀疑现在几乎不可能找到溢出 - 例如:
uint8_t example[50];
uint8_t example2[100];
for(uint8_t i = 0; i < sizeof(example2); i++)
example[i] = i;
我明白上面的代码示例是原始的。这只是我要描述的示例。
是否有可用的包或函数可以检测这些“泄漏”?
带有标志 -Wall
的最新版本的 GCC 将检测简单的错误,例如您示例中的问题,并打印警告。
工具 Valgrind 更高级,但也需要更多工作才能正确配置和使用。
宇宙中没有一种工具可以检测出所有可能的错误,所以从最容易使用的开始。
静态分析只能做这么多,但这里有一些我每天都在使用的工具:
此外,正如 Tom V 指出的那样,打开尽可能多的警告(-Wall
是最小值 - here 是一组很好的警告标志起始集)。
GCC 警告 out-of-bound 此类问题。使用 -Wall -pedantic -O1
:
编译此代码示例
int main(void) {
int example[50];
for (int i = 0; i < 100; i++)
example[i] = i;
return example[0];
}
...导致此编译警告(使用 ARM GCC 11.2 (linux),可在 Godbolt 上测试,正如 Tom V 的回答中已经指出的那样:
<source>: In function 'main':
<source>:4:20: warning: iteration 50 invokes undefined behavior [-Waggressive-loop-optimizations]
4 | example[i] = i;
| ~~~~~~~~~~~^~~
<source>:3:23: note: within this loop
3 | for (int i = 0; i < 100; i++)
| ~~^~~~~
Compiler returned: 0
在这种情况下,需要优化选项标志 -O1
(或 -O2
、-Os
)才能从 GCC 获取未定义的行为警告。 -O3
优化了loop out,所以不会有警告。没有优化(默认选项 -O0
)也不会导致警告,因为据我所知,GCC 显然只在优化循环时注意到 out-of-bound 问题(参见 -Waggressive-loop-optimizations
)。
(一些注意事项:
GCC 的 -fstack-check
和 -fstack-protector
选项也值得一看(运行时检查)。 Valgrind 或其他 static/dynamic 分析工具也很有用。然而,在微控制器上,在运行时在目标上分析程序通常不是那么容易,模拟器或在开发机器上用不同的编译器编译程序的 non-platform 特定部分也有帮助,使它更僵硬。
相关主题已在此处讨论:Accessing an array out of bounds gives no error, why?, How does the gcc option -fstack-check exactly work?)
工具 Frama-c ,通过 Eva 插件,允许进行值分析:它能够计算每个变量的每个可能值,然后检测(除其他问题外)数组溢出,即使在非平凡的代码中也是如此来源。
我被咬了几次屁股,我会写一个超出范围的数组。我已经在一个特定的固件上工作了 2 年多,并且怀疑现在几乎不可能找到溢出 - 例如:
uint8_t example[50];
uint8_t example2[100];
for(uint8_t i = 0; i < sizeof(example2); i++)
example[i] = i;
我明白上面的代码示例是原始的。这只是我要描述的示例。
是否有可用的包或函数可以检测这些“泄漏”?
带有标志 -Wall
的最新版本的 GCC 将检测简单的错误,例如您示例中的问题,并打印警告。
工具 Valgrind 更高级,但也需要更多工作才能正确配置和使用。
宇宙中没有一种工具可以检测出所有可能的错误,所以从最容易使用的开始。
静态分析只能做这么多,但这里有一些我每天都在使用的工具:
此外,正如 Tom V 指出的那样,打开尽可能多的警告(-Wall
是最小值 - here 是一组很好的警告标志起始集)。
GCC 警告 out-of-bound 此类问题。使用 -Wall -pedantic -O1
:
int main(void) {
int example[50];
for (int i = 0; i < 100; i++)
example[i] = i;
return example[0];
}
...导致此编译警告(使用 ARM GCC 11.2 (linux),可在 Godbolt 上测试,正如 Tom V 的回答中已经指出的那样:
<source>: In function 'main':
<source>:4:20: warning: iteration 50 invokes undefined behavior [-Waggressive-loop-optimizations]
4 | example[i] = i;
| ~~~~~~~~~~~^~~
<source>:3:23: note: within this loop
3 | for (int i = 0; i < 100; i++)
| ~~^~~~~
Compiler returned: 0
在这种情况下,需要优化选项标志 -O1
(或 -O2
、-Os
)才能从 GCC 获取未定义的行为警告。 -O3
优化了loop out,所以不会有警告。没有优化(默认选项 -O0
)也不会导致警告,因为据我所知,GCC 显然只在优化循环时注意到 out-of-bound 问题(参见 -Waggressive-loop-optimizations
)。
(一些注意事项:
GCC 的 -fstack-check
和 -fstack-protector
选项也值得一看(运行时检查)。 Valgrind 或其他 static/dynamic 分析工具也很有用。然而,在微控制器上,在运行时在目标上分析程序通常不是那么容易,模拟器或在开发机器上用不同的编译器编译程序的 non-platform 特定部分也有帮助,使它更僵硬。
相关主题已在此处讨论:Accessing an array out of bounds gives no error, why?, How does the gcc option -fstack-check exactly work?)
工具 Frama-c ,通过 Eva 插件,允许进行值分析:它能够计算每个变量的每个可能值,然后检测(除其他问题外)数组溢出,即使在非平凡的代码中也是如此来源。