0

World! I am bad at dynamic memory allocation so please help me! The problem is that when i compile c file without sanitizer it executes normally.

#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;
}

here what sanitizer says:

==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
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
bibaboba
  • 3
  • 1

2 Answers2

3

You have a problem in

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

for the very first iteration, i is 1, so the index value is -1, which is an invalid index.

That said, couple of more important things:

  • Memory returned by malloc() is uninitialised. If you try to read it before you assign any value to the memory, you'll be hit with indeterminate value and the program behaviour is not predictable.

  • The syntax

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

    is a very problematic one, in case realloc() fails and returns a NULL, you'll end up losing the original pointer, too!

    Always check for success of the realloc() call before assigning the returned value to the variable, something like

    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..

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
1

Since you're using a POSIX system, just use the wheel instead of reinventing it:

#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);
}

Should you ever need to venture to the lesser systems, there are many implementations for standard getline using just standard C library facilities.