Memory leak error in scanf-like function

In the code below, I am trying to recreate scanfto read everything from stdinand break a new character in a string, returning all the characters read in a string.

But the problem is that the code loses some memory, especially when called realloc.

I would also like to know why a getsdangerous function to use

test.c: warning: the 'gets' function is dangerous and should not be used.

My code: -

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

#define MAX_BUF_LEN 128
#define __cdecl

//0 - Success
//-1 - Error in input
//1 - Error
__cdecl int read_input(char *s,int len){

char c,*t;
int l,i=0;

if(s==NULL || len < 1)
    return -1;

while((c=getchar()) != '\n'){

    //check if sufficient memory
    //required + used > assigned 
    l=strlen(s);
    if(l + 2 > len){

        len += l + MAX_BUF_LEN;     //realloc max to avoid subsequent realloc as its costly!

        t = realloc(s,len);
        if(t!=NULL)
            s = t;
        else
            return 1;               //No space to store content
    }

    s[i++] = c;

}

s[i++] = '\0';      //Null terminate the Buffer
return 0;   
}

int main(int argc,char* argv[]){

int len = 5+1;
char *s = calloc(len,sizeof(char));

printf("Enter your name\n");

if(!read_input(s,len))
    printf("Hi %s\n",s);

free(s);

return 0;
}

Valgrind:

nimish:~/Desktop$ gcc -g -Wall test.c -o test
nimish~/Desktop$ clear && valgrind ./test  --leak-check=full

==3670== Memcheck, a memory error detector
==3670== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==3670== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==3670== Command: ./test --leak-check=full
==3670== 
Enter your name
Nimish Nicolus
==3670== Conditional jump or move depends on uninitialised value(s)
==3670==    at 0x4027029: strlen (mc_replace_strmem.c:282)
==3670==    by 0x804850E: read_input (test.c:23)
==3670==    by 0x80485CD: main (test.c:51)
==3670== 
==3670== Invalid read of size 1
==3670==    at 0x40831BF: vfprintf (vfprintf.c:1623)
==3670==    by 0x40891BF: printf (printf.c:35)
==3670==    by 0x80485E6: main (test.c:52)
==3670==  Address 0x41a5028 is 0 bytes inside a block of size 6 free'd
==3670==    at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670==    by 0x8048537: read_input (test.c:28)
==3670==    by 0x80485CD: main (test.c:51)
==3670== 
==3670== Invalid read of size 1
==3670==    at 0x40A93A8: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1317)
==3670==    by 0x408346F: vfprintf (vfprintf.c:1623)
==3670==    by 0x40891BF: printf (printf.c:35)
==3670==    by 0x80485E6: main (test.c:52)
==3670==  Address 0x41a502c is 4 bytes inside a block of size 6 free'd
==3670==    at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670==    by 0x8048537: read_input (test.c:28)
==3670==    by 0x80485CD: main (test.c:51)
==3670== 
==3670== Invalid read of size 1
==3670==    at 0x40A93BF: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1317)
==3670==    by 0x408346F: vfprintf (vfprintf.c:1623)
==3670==    by 0x40891BF: printf (printf.c:35)
==3670==    by 0x80485E6: main (test.c:52)
==3670==  Address 0x41a502b is 3 bytes inside a block of size 6 free'd
==3670==    at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670==    by 0x8048537: read_input (test.c:28)
==3670==    by 0x80485CD: main (test.c:51)
==3670== 
==3670== Invalid read of size 1
==3670==    at 0x40A9330: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1349)
==3670==    by 0x408346F: vfprintf (vfprintf.c:1623)
==3670==    by 0x40891BF: printf (printf.c:35)
==3670==    by 0x80485E6: main (test.c:52)
==3670==  Address 0x41a5028 is 0 bytes inside a block of size 6 free'd
==3670==    at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670==    by 0x8048537: read_input (test.c:28)
==3670==    by 0x80485CD: main (test.c:51)
==3670== 
==3670== Invalid read of size 1
==3670==    at 0x40A933C: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1348)
==3670==    by 0x408346F: vfprintf (vfprintf.c:1623)
==3670==    by 0x40891BF: printf (printf.c:35)
==3670==    by 0x80485E6: main (test.c:52)
==3670==  Address 0x41a502a is 2 bytes inside a block of size 6 free'd
==3670==    at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670==    by 0x8048537: read_input (test.c:28)
==3670==    by 0x80485CD: main (test.c:51)
==3670== 
Hi Nimis
==3670== Invalid free() / delete / delete[]
==3670==    at 0x4025BF0: free (vg_replace_malloc.c:366)
==3670==    by 0x80485F2: main (test.c:54)
==3670==  Address 0x41a5028 is 0 bytes inside a block of size 6 free'd
==3670==    at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670==    by 0x8048537: read_input (test.c:28)
==3670==    by 0x80485CD: main (test.c:51)
==3670== 
==3670== 
==3670== HEAP SUMMARY:
==3670==     in use at exit: 139 bytes in 1 blocks
==3670==   total heap usage: 2 allocs, 2 frees, 145 bytes allocated
==3670== 
==3670== LEAK SUMMARY:
==3670==    definitely lost: 139 bytes in 1 blocks
==3670==    indirectly lost: 0 bytes in 0 blocks
==3670==      possibly lost: 0 bytes in 0 blocks
==3670==    still reachable: 0 bytes in 0 blocks
==3670==         suppressed: 0 bytes in 0 blocks
==3670== Rerun with --leak-check=full to see details of leaked memory
==3670== 
==3670== For counts of detected and suppressed errors, rerun with: -v
==3670== Use --track-origins=yes to see where uninitialised values come from
==3670== ERROR SUMMARY: 23 errors from 7 contexts (suppressed: 11 from 6)

EDIT: - PLEASE READ THE NEW CODE ANNEXED BELOW

New code: -

__cdecl int read_input(char **s,int len){

char c,*t;
int l,i=0;

if((*s)==NULL || len < 1)
    return -1;

while((c=getchar()) != '\n'){

    //check if sufficient memory
    //required + used > assigned 
    l=strlen((*s));
    if(l + 2 > len){

        len += l + MAX_BUF_LEN;     //realloc max to avoid subsequent realloc as its costly!

        t = realloc((*s),len);
        if(t!=NULL)
            (*s) = t;
        else
            return 1;               //No space to store content
    }

    *((*s)+i++) = c;

}

*((*s)+i) = '\0';       //Null terminate the Buffer
return 0;   
} 

Valgrind:

==4767== Memcheck, a memory error detector
==4767== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==4767== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==4767== Command: ./test --leak-check=full
==4767== 
Enter your name
Nimish Nicolus
==4767== Conditional jump or move depends on uninitialised value(s)
==4767==    at 0x4027029: strlen (mc_replace_strmem.c:282)
==4767==    by 0x8048516: read_input (test.c:23)
==4767==    by 0x80485DE: main (test.c:51)
==4767== 
Hi Nimish Nicolus
==4767== 
==4767== HEAP SUMMARY:
==4767==     in use at exit: 0 bytes in 0 blocks
==4767==   total heap usage: 2 allocs, 2 frees, 145 bytes allocated
==4767== 
==4767== All heap blocks were freed -- no leaks are possible
==4767== 
==4767== For counts of detected and suppressed errors, rerun with: -v
==4767== Use --track-origins=yes to see where uninitialised values come from
==4767== ERROR SUMMARY: 6 errors from 1 contexts (suppressed: 11 from 6)

It still gives some problem.

+3
source share
4 answers

Here is what the manual says about the problem gets:

gets(). , , (), gets() , , . . fgets().

- , s , , , , . , s , , realloc -ed. , read_input , :

int read_input(char **ps,int len)

&s read_input (*ps) s .

+4

. , free(s) , . realloc . , . int NULL .

PS - , .

+3

:

l=strlen(s);

s . , strlen(), , , . , .

gets , , , .

+2

gets () is dangerous because it has no information about how large your buffer is, so it cannot prevent buffer overflows on a large input line. For bad guys, buffer overflows are one very common attack vector. Instead, use fgets () with stdin as the first parameter, which allows you to specify how large the buffer is.

+2
source

All Articles