Akaash
Akaash

Reputation: 69

What if memory is not allocated to '\0' in char array and char pointer

The following two programs are almost similar. In the two programs, memory is not allocated for null('\0') character.

Ex A:

void main()
{
        char *ptr;
        ptr = (char *)malloc(2);
        strcpy(ptr, "ls");
        printf("%s\n",ptr);
        system(ptr);
        free(ptr);
}

Ex B:

void main()
{
        char ptr[2] = "ls"; 
        system(ptr);
}

1.The first program(Ex. A) is working But i have seen error only with valgrind tool.

output

[root@localhost tmp]# valgrind --leak-check=full ./a.out 
==8619== Memcheck, a memory error detector
==8619== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8619== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8619== Command: ./a.out
==8619== 
==8619== Invalid write of size 1
==8619==    at 0x400635: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8619==  Address 0x51f2042 is 0 bytes after a block of size 2 alloc'd
==8619==    at 0x4C29C4F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8619==    by 0x400627: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8619== 
==8619== Invalid read of size 1
==8619==    at 0x4C2CC14: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8619==    by 0x4EA4D3B: puts (in /usr/lib64/libc-2.20.so)
==8619==    by 0x400644: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8619==  Address 0x51f2042 is 0 bytes after a block of size 2 alloc'd
==8619==    at 0x4C29C4F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8619==    by 0x400627: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8619== 
ls
==8620== Syscall param execve(argv[i]) points to unaddressable byte(s)
==8620==    at 0x4EF9537: execve (in /usr/lib64/libc-2.20.so)
==8620==    by 0x4E77D18: do_system (in /usr/lib64/libc-2.20.so)
==8620==    by 0x400650: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8620==  Address 0x51f2042 is 0 bytes after a block of size 2 alloc'd
==8620==    at 0x4C29C4F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8620==    by 0x400627: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8620== 
a.out  test37.c
==8619== 
==8619== HEAP SUMMARY:
==8619==     in use at exit: 0 bytes in 0 blocks
==8619==   total heap usage: 1 allocs, 1 frees, 2 bytes allocated
==8619== 
==8619== All heap blocks were freed -- no leaks are possible
==8619== 
==8619== For counts of detected and suppressed errors, rerun with: -v
==8619== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

2.But the second one is not working

Ex B

[root@localhost Cprgm]# ./a.out 
sh: $'ls%\211\376\177': command not found

Why this happens?

Upvotes: 0

Views: 123

Answers (3)

Sourav Ghosh
Sourav Ghosh

Reputation: 134336

TL;DR both the codes cause undefined behavior.

  • In first case

    ptr = (char *)malloc(2);
    strcpy(ptr, "ls");
    

    you're off-by-one, as mentioned in C11, chapter §7.24.2.3,

    The strcpy function copies the string pointed to by s2 (including the terminating null character) into the array pointed to by s1.

    So, the size of s1 should at least be strlen(s2)+ 1.

  • In second case

    char ptr[2] = "ls";
    

    ptr does not have a null-terminator which in essence, causes out of bound access which again causes UB.

    Related, quoting the POSIX manual,

    [...] If command is not a null pointer, the system() function shall pass the string pointed to by command to that command processor to be executed in an implementation-defined manner; [...]

    A char array, without a null-terminator in place, is not considered a string.


Having said that, there are a few sggestions,

Upvotes: 3

DineshB
DineshB

Reputation: 37

In the first case:

ptr = (char *)malloc(2);

memory is allocated for two bytes but strcpy stored 3 bytes at this location. So it is basically a memory corruption case but still "ls" command with \0 at the end is stored at the location which makes system command to work.

In the second case:

char ptr[2] = "ls";

This assignment itself is wrong and is not supposed to work. Behaviour is undefined.

Upvotes: -1

Vishwajeet Vishu
Vishwajeet Vishu

Reputation: 492

The array that you used in Ex B is only of length 2. whenever you store a string in a array "ls" automatically a null character is added with is '\0' so "ls" will become l s \0 when it is stored in memory. Most of the algorithm are based on this NULL character to find the length of string of value of string.

So just declare your array of length 3 and you will be good to go.

Thanks.

Upvotes: 0

Related Questions