c - 是否有检测 C 程序中的内存错误的解决方案?
问题描述
我正在编写 C lib 函数并且有关于内存的问题。对于strcpy()
功能:
char *my_strcpy(char *str1, char *str2)
{
int i = 0;
for (; str2[i] != 0; i++)
str1[i] = str2[i];
str1[i] = 0;
return (str1);
}
使用以下标准测试:
#include <criterion/criterion.h>
char *my_strcpy(char *str1, char *str2);
Test(my_strcpy, in_allocated_string)
{
char *src = "Hello World";
char dest[11];
my_strcpy(dest, src);
cr_assert_str_eq(dest, "Hello World");
cr_assert_eq(dest, my_strcpy(dest, src));
}
目标缓冲区小于源缓冲区,因此它不应该工作......但它可以工作。Valgrind 或扫描构建不会给我任何错误,它编译并运行没有错误......
用于编译和运行测试的 Makefile:
SRC = code.c \
SRC_TEST = test.c \
LDFLAGS = -L./lib/my -lmy
OBJ = $(SRC:.c=.o)
CC = gcc
CFLAGS = -W -Wall -Wextra -Werror -fstack-protector -fstack-protector-all -fstack-protector-strong -Wstack-protector
NAME = libmy.a
all: $(NAME)
$(NAME): $(OBJ)
ar rc $@ $^
test: $(SRC) $(SRC_TEST)
$(CC) -fprofile-arcs -ftest-coverage -Isrc/main -DMOCKING $(CFLAGS) $(shell pkg-config --libs --cflags criterion) $^ -o tests
./tests
clean:
rm -rf *.gcda *.gcno *.info $(OBJ)
fclean: clean
rm -f $(NAME)
rm -rf tests
re: fclean all
是否有检测 C 程序中的内存错误的解决方案?
解决方案
Valgrind 的 Memcheck对堆栈上分配的数组有一些限制。由于它适用于正常编译的二进制文件,因此在某些情况下它无法知道确切的数组大小。
clang 的AddressSanitizer在这方面做得更好。如果你用 编译-fsanitize=address
,你会得到以下错误:
=================================================================
==15908==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffdb7e06beb at pc 0x0000005286d2 bp 0x7ffdb7e06b40 sp 0x7ffdb7e06b38
WRITE of size 1 at 0x7ffdb7e06beb thread T0
#0 0x5286d1 in my_strcpy (/home/runner/.bin.tio+0x5286d1)
#1 0x52883d in main (/home/runner/.bin.tio+0x52883d)
#2 0x7ff3e3fae412 in __libc_start_main (/lib64/libc.so.6+0x24412)
#3 0x41b33d in _start (/home/runner/.bin.tio+0x41b33d)
Address 0x7ffdb7e06beb is located in stack of thread T0 at offset 43 in frame
#0 0x5286ff in main (/home/runner/.bin.tio+0x5286ff)
This frame has 1 object(s):
[32, 43) '.compoundliteral' <== Memory access at offset 43 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/runner/.bin.tio+0x5286d1) in my_strcpy
Shadow bytes around the buggy address:
0x100036fb8d20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100036fb8d30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100036fb8d40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100036fb8d50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100036fb8d60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100036fb8d70: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00[03]f3 f3
0x100036fb8d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100036fb8d90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100036fb8da0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100036fb8db0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100036fb8dc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==15908==ABORTING
推荐阅读
- jquery - JQuery 3.5.1 并拒绝执行内联脚本,因为它违反了以下内容安全策略指令:
- parsing - 模棱两可的上下文无关语法?/ 移位/减少 CUP 中的冲突
- ms-access-2016 - 计算空字段
- javascript - 坐标计算:如何将旋转的 HTML 主体上的对象分别转换为 0 度旋转主体
- javascript - 如何完全从 JavaScript 定义 CSS 动画?
- google-apps-script - UrlFetchApp.fetch() 在约 4 秒后突然产生“异常:超时”错误
- typescript - 尝试在模块中传递环境变量
- firebase-realtime-database - 如何处理 Firebase 电子邮件警告
- java - 如何从Java中的聚合桶中获取值以获取elasticsearch聚合查询结果
- java - 为什么我得到:'%','(',
,, '?', FUNCTION 或标识符,得到 '('?