Valgrind memcheck invalid read of size 1 - c

This example can be compiled and works as expected.
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 char * getstr() {
6 return strdup("Hello");
7 }
8
9 void *memcpy2(void *dest, const void *src, size_t len)
10 {
11 char * d = dest;
12 const char * s = src;
13
14 for (size_t i = 0; i < len; i++) {
15 d[i] = s[i];
16 }
17 return dest;
18 }
19
20 int main()
21 {
22 char buf[256];
23 char *str = getstr();
24
25 memset(buf, 0, 256);
26 memcpy2(buf, str, 255);
27
28 printf("%s\n", buf);
29
30 free(str);
31 return 0;
32 }
I reimplemented memcpy to have complete control over the test, making it independent from underlaying libc. As you can see, valgrind complains with this warning:
$ valgrind ./a.out
==9479== Memcheck, a memory error detector
==9479== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9479== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9479== Command: ./a.out
==9479==
==9479== Invalid read of size 1
==9479== at 0x4006B6: memcpy2 (k.c:15)
==9479== by 0x400731: main (k.c:26)
==9479== Address 0x5203046 is 0 bytes after a block of size 6 alloc'd
==9479== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9479== by 0x4EC48D9: strdup (strdup.c:42)
==9479== by 0x400673: getstr (k.c:6)
==9479== by 0x4006F3: main (k.c:23)
==9479==
Hello
==9479==
==9479== HEAP SUMMARY:
==9479== in use at exit: 0 bytes in 0 blocks
==9479== total heap usage: 2 allocs, 2 frees, 1,030 bytes allocated
==9479==
==9479== All heap blocks were freed -- no leaks are possible
==9479==
==9479== For counts of detected and suppressed errors, rerun with: -v
I don't understand why this "invalid read of size 1" message appears. It has not sense for me at all. Can some of you explain what is wrong with this code? Thank you in advance!

[...]
for (size_t i = 0; i < len; i++) {
d[i] = s[i];
}
[...]
Here len is 255, but the string pointed by s is less than 255 length, so you're going out of the array. You could maybe use the '\0' placed by strdup() to avoid this bug.

In main the str variable points to a memory area of six bytes length (the string "Hello" is the five characters in the string plus terminator, strdup will allocate strlen("Hello") + 1 bytes). Going out of bounds leads to undefined behavior.
And you are going out of bounds since you want to read 255 bytes from this six-byte area.

Related

Valgrind leak of memory in a function that concatenates strings

I using valgrind to find a leak of memory. I wrote a function "prefix_to_string" to concatenate any two strings, but when I use the command
valgrind --leak-check=full ./helloworld
it says that I have a lot of leaks of memory. I really don't know where and why. I asked a friend why it was happening and he says that it was for doing malloc 2 times, 1 out the function and 1 in the function, but I don't know how to take care of that leak, because I think that I need to do those memory requests.
Here is the output that Valgrind gives me:
==9078== Memcheck, a memory error detector
==9078== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9078== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9078== Command: ./holamundo
==9078==
==9078== error calling PR_SET_PTRACER, vgdb might block
150:62
bye
==9078==
==9078== HEAP SUMMARY:
==9078== in use at exit: 63 bytes in 4 blocks
==9078== total heap usage: 5 allocs, 1 frees, 575 bytes allocated
==9078==
==9078== 5 bytes in 1 blocks are definitely lost in loss record 1 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008AC: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 7 bytes in 1 blocks are definitely lost in loss record 2 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008C3: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 8 bytes in 1 blocks are definitely lost in loss record 3 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008D8: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 43 bytes in 1 blocks are definitely lost in loss record 4 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400897: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== LEAK SUMMARY:
==9078== definitely lost: 63 bytes in 4 blocks
==9078== indirectly lost: 0 bytes in 0 blocks
==9078== possibly lost: 0 bytes in 0 blocks
==9078== still reachable: 0 bytes in 0 blocks
==9078== suppressed: 0 bytes in 0 blocks
==9078==
==9078== For counts of detected and suppressed errors, rerun with: -v
==9078== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
and here is the main of my code, so this way you can reproduce the problem:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
char* prefix_to_string(char* first_string,char* second_string){
char* name = first_string;
char* extension = second_string;
char* name_with_extension;
name_with_extension = malloc(strlen(name)*(sizeof(char))+strlen(extension)*(sizeof(char))+1); /* make space for the new string (should check the return value ...) */
strcpy(name_with_extension, name); /* copy name into the new var */
strcat(name_with_extension, extension); /* add the extension */
return name_with_extension;
}
static char *itoa_simple_helper(char *dest, int i) {
if (i <= -10) {
dest = itoa_simple_helper(dest, i/10);
}
*dest++ = '0' - i%10;
return dest;
}
char *itoa_simple(char *dest, int i) {
char *s = dest;
if (i < 0) {
*s++ = '-';
} else {
i = -i;
}
*itoa_simple_helper(s, i) = '\0';
return dest;
}
int main(int argc, char *argv[]) {
int idx = 150;
int id = 62;
char str_idx[20];
char str_id[20];
itoa_simple( str_idx ,idx);
itoa_simple( str_id,id);
char *text_to_write;
text_to_write = malloc(2+sizeof(str_id)+sizeof(str_idx)+1);
text_to_write = prefix_to_string(str_idx,":");
text_to_write = prefix_to_string(text_to_write,str_id);
text_to_write = prefix_to_string(text_to_write,"\n");
printf("%s",text_to_write);
printf("bye\n");
free(text_to_write);
return 1;
}
You don't call free() often enough — you can't expect to avoid memory leaks if you don't call free() to release each separate memory allocation. And your repeated assignments to text_to_write in main() mean that you discard the only pointers to some of the allocated memory, so you can't free what was allocated. C requires endless care with memory management.
You have:
char *text_to_write;
text_to_write = malloc(2+sizeof(str_id)+sizeof(str_idx)+1);
// This assignment throws away the memory from the previous malloc
text_to_write = prefix_to_string(str_idx,":");
// This assignment throws away the memory from the previous prefix_to_string
text_to_write = prefix_to_string(text_to_write,str_id);
// This assignment also throws away the memory from the previous prefix_to_string
text_to_write = prefix_to_string(text_to_write,"\n");
printf("%s",text_to_write);
printf("bye\n");
// Calling free here only releases the last allocation from prefix_to_string
free(text_to_write);
You need something more like:
char *part1 = prefix_to_string(str_idx, ":");
char *part2 = prefix_to_string(part1, str_id);
char *part3 = prefix_to_string(part2, "\n");
printf("%s", part3);
printf("bye\n");
free(part1);
free(part2);
free(part3);

Valgrind complains when function returns char array pointer

I guess this is a newbie C question but I just could not find the answer. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *copy(char *in) {
char *out = (char *) malloc(strlen(in)+1);
strcpy(out,in);
return out;
}
int main() {
char *orig = (char *) malloc(100);
strcpy(orig,"TEST");
printf("Original reads : %s\n",orig);
printf("Copy reads : %s\n",copy(orig));
}
It works fine, however valgrind --leak-check=yes complains:
==4701== Memcheck, a memory error detector
==4701== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4701== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==4701== Command: ./copy
==4701==
Original reads : TEST
Copy reads : TEST
==4701==
==4701== HEAP SUMMARY:
==4701== in use at exit: 105 bytes in 2 blocks
==4701== total heap usage: 2 allocs, 0 frees, 105 bytes allocated
==4701==
==4701== 5 bytes in 1 blocks are definitely lost in loss record 1 of 2
==4701== at 0x4C28C20: malloc (vg_replace_malloc.c:296)
==4701== by 0x400609: copy (in /root/alfred/copy)
==4701== by 0x40066C: main (in /root/alfred/copy)
==4701==
==4701== 100 bytes in 1 blocks are definitely lost in loss record 2 of 2
==4701== at 0x4C28C20: malloc (vg_replace_malloc.c:296)
==4701== by 0x400638: main (in /root/alfred/copy)
==4701==
==4701== LEAK SUMMARY:
==4701== definitely lost: 105 bytes in 2 blocks
==4701== indirectly lost: 0 bytes in 0 blocks
==4701== possibly lost: 0 bytes in 0 blocks
==4701== still reachable: 0 bytes in 0 blocks
==4701== suppressed: 0 bytes in 0 blocks
==4701==
==4701== For counts of detected and suppressed errors, rerun with: -v
==4701== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Could someone please tell me what am I doing wrong? Thanks in advance!
You are malloc()'ing twice but do not free() them. Hence, valgrind complains about leaks.
Free the memory blocks you allocate and it should be fine.
char *p = copy(orig);
printf("Copy reads : %s\n", p);
free(orig);
free(p);
You are allocating memory block in the copy function, but never free it. So your code produces a memory leak, which is reported by the Valgrind. Correct version of your code should be
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *copy(char *in) {
char *out = malloc(strlen(in)+1);
//You need to check malloc result here!
strcpy(out,in);
return out;
}
int main() {
char *orig = (char *) malloc(100);
strcpy(orig,"TEST");
printf("Original reads : %s\n",orig);
char* copy = copy(orig);
printf("Copy reads : %s\n",copy);
free(orig);
free(copy);
return 0;
}
Also do not cast malloc() results.

Read in Words from Text File and Store into Dynamic Array Valgrind Errors in C

I'm trying to read in words from a text file in C using fscanf and putthem into a dynamically allocated array. However, I keep getting errors in Valgrind and (null) characters seem to be popping up in my output. I create a double pointer **str_array to hold each character array and initially allocate enough space for 4 character arrays. fscanf runs and stores the read in string into str[] and I use strcpy to copy str[]'s string into str_array. I realloc memory if str_array needs to hold more strings.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char str[80];
int word_alloc = 0;
int word_count = 0;
char **str_array;
FILE *file;
file = fopen(argv[1], "r");
// Allocate memory to the array of strings (char arrays)
word_alloc = 4;
str_array = (char **) malloc(sizeof(char*) * word_alloc);
while (fscanf(file, "%s", str) != EOF) {
// If there are more than 4 strings, double size
if (word_count > word_alloc) {
word_alloc *= 2;
str_array = (char **) realloc(str_array, sizeof(char*) * word_alloc);
}
str_array[word_count] = (char *) malloc(sizeof(char) * (strlen(str) + 1));
strcpy(str_array[word_count], str);
++word_count;
}
int i = 0;
for (; i<word_count; i++) {
printf("Word: %s\n", str_array[i]);
}
i = 0;
for (; i<word_count; i++) {
free(str_array[word_count]);
}
free(str_array);
fclose(file);
return 0;
}
Here's the Valgrind error code.
==6254== Memcheck, a memory error detector
==6254== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6254== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==6254== Command: ./a.out readin-test.txt
==6254==
==6254== Invalid write of size 8
==6254== at 0x4008A6: main (readin-test.c:25)
==6254== Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400835: main (readin-test.c:16)
==6254==
==6254== Invalid read of size 8
==6254== at 0x4008C0: main (readin-test.c:26)
==6254== Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400835: main (readin-test.c:16)
==6254==
==6254== Conditional jump or move depends on uninitialised value(s)
==6254== at 0x4C2BDA2: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x40094A: main (readin-test.c:37)
==6254== Uninitialised value was created by a heap allocation
==6254== at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400871: main (readin-test.c:22)
==6254==
==6254==
==6254== HEAP SUMMARY:
==6254== in use at exit: 999 bytes in 173 blocks
==6254== total heap usage: 181 allocs, 8 frees, 5,631 bytes allocated
==6254==
==6254== 999 bytes in 173 blocks are definitely lost in loss record 1 of 1
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x4008A5: main (readin-test.c:25)
==6254==
==6254== LEAK SUMMARY:
==6254== definitely lost: 999 bytes in 173 blocks
==6254== indirectly lost: 0 bytes in 0 blocks
==6254== possibly lost: 0 bytes in 0 blocks
==6254== still reachable: 0 bytes in 0 blocks
==6254== suppressed: 0 bytes in 0 blocks
==6254==
==6254== For counts of detected and suppressed errors, rerun with: -v
==6254== ERROR SUMMARY: 186 errors from 4 contexts (suppressed: 0 from 0)
You have an error in the free loop:
i = 0;
for (; i<word_count; i++) {
free(str_array[word_count]);
}
The array index should be i, not word_count.

I don't understand why I get this valgrind error

I got the following code:
/* main.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (){
int i;
char *msg = "This is a simple and small message";
int len = strlen (msg);
char *new_msg = (char *) malloc (len);
for (i = 0; i < len; i++)
new_msg[i] = 'A';
printf ("%s\n", new_msg);
free (new_msg);
return 0;
}
I compiled it and then run it using valgrind with this command:
valgrind --leak-check=full --show-reachable=yes ./main
I got the this output:
==8286== Memcheck, a memory error detector
==8286== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8286== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8286== Command: ./main
==8286==
==8286== Invalid read of size 1
==8286== at 0x4C2C1B4: strlen (vg_replace_strmem.c:412)
==8286== by 0x4EA09FB: puts (ioputs.c:36)
==8286== by 0x400636: main (main.c:12)
==8286== Address 0x51de062 is 0 bytes after a block of size 34 alloc'd
==8286== at 0x4C28C20: malloc (vg_replace_malloc.c:296)
==8286== by 0x400601: main (main.c:9)
==8286==
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
==8286==
==8286== HEAP SUMMARY:
==8286== in use at exit: 0 bytes in 0 blocks
==8286== total heap usage: 1 allocs, 1 frees, 34 bytes allocated
==8286==
==8286== All heap blocks were freed -- no leaks are possible
==8286==
==8286== For counts of detected and suppressed errors, rerun with: -v
==8286== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I see that all the allocated memory was released, but I still get an error that I don't understand.
Appreciate the help.
This is a pretty straightforward error: there is an invalid read of new_msg because the null terminator is not there.
You have allocated the number of chars equal to the length of the original string, so currently there's no space to fit '\0' without making undefined behavior. Change your code as follows to fix the problem:
char *new_msg = malloc (len+1);
for (i = 0; i < len; i++)
new_msg[i] = 'A';
new_msg[len] = '\0';
There are a number of things to be changes in your code.
1) len should be of size_t not int, as strlen() returns of type size_t
2) (char *) malloc (len); drop the cast. This isn't an error, although there are reasons one should not cast.
3) new_msg is not NULL terminated \0. This is the reason the error is occurring.
you use strlen() to get length, but not contain the '\0'.
so when you malloc a new array, you should use len + 1, and set new_msg[len] is '\0'.

C strings, strlen and Valgrind

I'm trying to understand why Valgrind is spitting out :
==3409== Invalid read of size 8
==3409== at 0x4EA3B92: __GI_strlen (strlen.S:31)
whenever I'm applying strlen on a dynamically allocated string?
Here is a short testcase :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *hello = "Hello World";
char *hello2;
/* Step 1 */
printf("Step 1\n");
printf("strlen : %lu\n",(unsigned long)strlen(hello));
/* Step 2 */
hello2 = calloc(12,sizeof(char));
hello2[0] = 'H';
hello2[1] = 'e';
hello2[2] = 'l';
hello2[3] = 'l';
hello2[4] = 'o';
hello2[5] = ' ';
hello2[6] = 'W';
hello2[7] = 'o';
hello2[8] = 'r';
hello2[9] = 'l';
hello2[10] = 'd';
hello2[11] = 0;
printf("Step 2\n");
printf("strlen : %lu\n",(unsigned long)strlen(hello2));
free(hello2);
return 0;
}
And here is the result output from Valgrind :
lenain#perseus:~/work/leaf$ valgrind ./leaf
==3409== Memcheck, a memory error detector
==3409== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3409== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info
==3409== Command: ./leaf
==3409==
Step 1
strlen : 11
Step 2
==3409== Invalid read of size 8
==3409== at 0x4EA3B92: __GI_strlen (strlen.S:31)
==3409== by 0x40098A: main (in /home/lenain/work/leaf/leaf)
==3409== Address 0x5189048 is 8 bytes inside a block of size 12 alloc'd
==3409== at 0x4C234CB: calloc (vg_replace_malloc.c:418)
==3409== by 0x4008F0: main (in /home/lenain/work/leaf/leaf)
==3409==
strlen : 11
==3409==
==3409== HEAP SUMMARY:
==3409== in use at exit: 0 bytes in 0 blocks
==3409== total heap usage: 1 allocs, 1 frees, 12 bytes allocated
==3409==
==3409== All heap blocks were freed -- no leaks are possible
==3409==
==3409== For counts of detected and suppressed errors, rerun with: -v
==3409== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
What is the correct way to avoid these warnings? Are they real warnings?
This is most likely related to this bugreport:
https://bugzilla.redhat.com/show_bug.cgi?id=518247
As Paul already suggested, strlen() on intel platforms optionally uses SSE optimization to speed up strlen and friends. This speed up involve safe reads behind the allocated blocks, something older versions of valgrind did not understand yet. So upgrade your valgrind and you will be OK.
My guess is that your strlen implementation has been optimised such that it reads 8 bytes at a time and tests for the first zero byte anywhere in the 64 bit word (probably using MMX/SSE). This means that for your 12 byte string example it's reading 4 bytes beyond the end of the string. It's arguable as to whether this is a bug in the strlen implementation or not. I think you'll just have to ignore it. Or make sure your string allocations are always multiples of 8 bytes.

Resources