Reputation: 69
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
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 bys2
(including the terminating null character) into the array pointed to bys1
.
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, thesystem()
function shall pass the string pointed to bycommand
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,
void main()
should at least be int main(void)
to conform to the standard.malloc()
and family in C
..Upvotes: 3
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
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