没有AddressSanitizer可以正常工作

时间:2020-10-07 07:10:48

标签: arrays c pointers dynamic-memory-allocation

世界!我不擅长动态内存分配,所以请帮助我!问题是,当我在不使用消毒剂的情况下编译c文件时,它会正常执行。

#include <stdio.h>
#include <stdlib.h>

int main()
{
        char *str = (char *)malloc(sizeof(char));
        int i = 1;
        while (str[i - 2] != '\n')
        {
                str = (char *)realloc(str, i * sizeof(char));
                str[i - 1] = getchar();
                i++;
        }
        str[++i] = '\0';
        fputs(str, stdout);
        free(str);
        return 0;
}

这是消毒剂说的:

==7174==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000000f at pc 0x55739456b340 bp 0x7fffba0090f0 sp 0x7fffba0090e0
READ of size 1 at 0x60200000000f thread T0
    #0 0x55739456b33f in main (/home/bek/diff1+0x133f)
    #1 0x7fd15ff780b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #2 0x55739456b1ad in _start (/home/bek/diff1+0x11ad)

0x60200000000f is located 1 bytes to the left of 1-byte region [0x602000000010,0x602000000011)
allocated by thread T0 here:
    #0 0x7fd160250bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #1 0x55739456b27e in main (/home/bek/diff1+0x127e)
    #2 0x7fd15ff780b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/bek/diff1+0x133f) in main

2 个答案:

答案 0 :(得分:3)

您有问题

 while (str[i - 2] != '\n')

对于第一次迭代,i1,因此索引值为-1,这是无效的索引。

那是另外一些重要的事情:

  • malloc()返回的内存未初始化。如果尝试在将任何值分配给内存之前先读取它,则会被不确定的值打中,并且程序的行为是不可预测的。

  • 语法

    str = (char *)realloc(str, i * sizeof(char));
    

    这是一个非常有问题的问题,万一realloc()失败并返回NULL,您也将失去原始指针!

    在将返回值分配给变量之前,始终检查realloc()调用是否成功,例如

    char * tmp = NULL;
    tmp = realloc(str, i);  // cast not needed, sizeof(char) == 1 in C
    if (!tmp) { exit(1); /* or cleanup*/}
    str = tmp;              // assign otherwise
    
  • Please see this discussion on why not to cast the return value of malloc() and family in C..

答案 1 :(得分:1)

由于您使用的是POSIX系统,因此只需使用轮子而不是重新发明轮子即可。

#define _POSIX_C_SOURCE 200809L
#include <stdio.h>

int main(void) {
    char *str = NULL;
    size_t n = 0;
    ssize_t result = getline(&str, &n, stdin);

    if (result < 0) {
        perror("An error occurred in getline");
        exit(1);
    }

    fputs(str, stdout);
    free(str);
}

如果您需要尝试使用较小的系统,则仅使用标准C库工具就可以实现许多标准getline的实现。