Valgrind complaining about uninitialized values - c

I have this little snippet here:
#include <string.h>
#include <stdio.h>
int main(void) {
char b[128];
strcpy(b, "four");
if(strcmp(b, "seven") == 0) {/* Line 9 */
printf("buffer 'b' contains \"%s\"\n", b);
}
else if(strcmp(b, "four") == 0) {
printf("buffer 'b' contains \"%s\"\n", b);
}
return 0;
}
If I compile it with Clang version "7.0.0-3~ubuntu0.18.04.1 (tags/RELEASE_700/final)" it is all nice and dandy even with -O3. If I do the same with Clang version "8.0.0-3~ubuntu18.04.2 (tags/RELEASE_800/final)" or later (checked version 9.0.0, too) with every optimization except -O0 Valgrind tells me
==17979== Memcheck, a memory error detector
==17979== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==17979== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==17979== Command: ./glibc_strcmp_x86_64_sse_4_2_bug
==17979==
==17979== Conditional jump or move depends on uninitialised value(s)
==17979== at 0x400540: main (glibc_strcmp_x86_64_sse_4_2_bug.c:9)
==17979== Uninitialised value was created by a stack allocation
==17979== at 0x400520: main (glibc_strcmp_x86_64_sse_4_2_bug.c:4)
==17979==
buffer 'b' contains "four"
==17979==
==17979== HEAP SUMMARY:
==17979== in use at exit: 0 bytes in 0 blocks
==17979== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==17979==
==17979== All heap blocks were freed -- no leaks are possible
==17979==
==17979== For counts of detected and suppressed errors, rerun with: -v
==17979== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
If I initialize the buffer with e.g.: char b[128] = {0}; it is OK, of course, no complains anymore. Or if I use a local version of strcmp.
Dumping the assembly outputs of each -O1 and -O0 respectively shows that the optimization of Clang-8 optimizes all occurrences of strcmp (and strcpy) away. Clang-7 does not do it, it calls all of the functions.
But who is to blame here? Is it a bug in Clang > 7? Or is my assumption wrong that strcmp, even if optimized away, should stop once either of the inputs reaches \0?

Related

Why doesn't valgrind detect this possible memory leak due to realloc?

I can't understand why valgrind (version 3.14) doesn't detect a possible memory leak in this program:
#include <stdlib.h>
int main() {
int *p = malloc(sizeof(int));
p = realloc(p, 2 * sizeof(int));
free(p);
return 0;
}
The C99 standard (ISO/IEC 9899:1999, page 314) says this about realloc:
If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged. [...]
The realloc function returns a pointer to the new object (which may have the same
value as a pointer to the old object), or a null pointer if the new object could not be
allocated.
So it may occur that p is NULL but the memory cell previously allocated with malloc is still there, shouldn't this be a possible memory leak?
If I compile the program with gcc -std=c99 and I execute valgrind with --tool=memcheck --leak-check=full --track-origins=yes it gives the following message:
==313618== Memcheck, a memory error detector
==313618== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==313618== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==313618== Command: ./a.out
==313618==
==313618==
==313618== HEAP SUMMARY:
==313618== in use at exit: 0 bytes in 0 blocks
==313618== total heap usage: 2 allocs, 2 frees, 12 bytes allocated
==313618==
==313618== All heap blocks were freed -- no leaks are possible
==313618==
==313618== For counts of detected and suppressed errors, rerun with: -v
==313618== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Valgrind does not analyze your code; it analyzes the actions taken by your code.
In this particular run realloc did not fail, so there was no memory leak, so valgrind had nothing to report:
All heap blocks were freed
And that's all valgrind knows.
To detect the problem in your code you need a static code analysis tool.

uninitialised value and clang optimizations

I have created a program to print "Hello World" string as bellow:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void callString(char *_string);
int main()
{
char *myString;
// Allocating memory
myString = (char *)malloc(
(unsigned long)strlen(myString)
* sizeof(char)
);
myString = "Hello World!";
callString(myString);
// should I free(myString) here?
return 0;
}
static void
callString(char *_string)
{
printf("%s\n", _string);
}
Compiling and running reports:
$ clang -Wall -Weverything -g hello.c -o hello
$ ./hello
Hello World!
Looks good, but then, if I try to profile memory using Valgrind, I get:
$ valgrind \
--track-origins=yes \
--leak-check=full \
--leak-resolution=high \
--num-callers=50 \
./hello
==31692== Memcheck, a memory error detector
==31692== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31692== Using Valgrind-3.14.0.GIT and LibVEX; rerun with -h for copyright info
==31692== Command: ./hello
==31692==
==31692== Use of uninitialised value of size 8
==31692== at 0x483ACC2: __strlen_sse2 (vg_replace_strmem.c:462)
==31692== by 0x109177: main (hello.c:9)
==31692== Uninitialised value was created by a stack allocation
==31692== at 0x109160: main (hello.c:7)
==31692==
==31692== Use of uninitialised value of size 8
==31692== at 0x483ACD4: __strlen_sse2 (vg_replace_strmem.c:462)
==31692== by 0x109177: main (hello.c:9)
==31692== Uninitialised value was created by a stack allocation
==31692== at 0x109160: main (hello.c:7)
==31692==
Hello World!
==31692==
==31692== HEAP SUMMARY:
==31692== in use at exit: 1 bytes in 1 blocks
==31692== total heap usage: 2 allocs, 1 frees, 1,025 bytes allocated
==31692==
==31692== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31692== at 0x483777F: malloc (vg_replace_malloc.c:299)
==31692== by 0x109183: main (hello.c:9)
==31692==
==31692== LEAK SUMMARY:
==31692== definitely lost: 1 bytes in 1 blocks
==31692== indirectly lost: 0 bytes in 0 blocks
==31692== possibly lost: 0 bytes in 0 blocks
==31692== still reachable: 0 bytes in 0 blocks
==31692== suppressed: 0 bytes in 0 blocks
==31692==
==31692== For counts of detected and suppressed errors, rerun with: -v
==31692== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
If I compile with optimization flags at -O3 level, I get green signal.
$ valgrind \
--track-origins=yes \
--leak-check=full \
--leak-resolution=high \
--num-callers=50 \
./hello
==32000== Memcheck, a memory error detector
==32000== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==32000== Using Valgrind-3.14.0.GIT and LibVEX; rerun with -h for copyright info
==32000== Command: ./hello
==32000==
Hello World!
==32000==
==32000== HEAP SUMMARY:
==32000== in use at exit: 0 bytes in 0 blocks
==32000== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==32000==
==32000== All heap blocks were freed -- no leaks are possible
==32000==
==32000== For counts of detected and suppressed errors, rerun with: -v
==32000== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
It looks like optimization fixes some of memory issues here. What's wrong with the code snippet? Which one is referred to "Use of uninitialised value"? myString? How can I initialize that?
Edit: As #Lundin advised, I have learnt the lesson not to assign strings with = directly. Thanks. Fixed code part =
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void callString(char *_string);
int main()
{
char *myString;
myString = (char *)malloc(
(unsigned long)strlen(myString)+1 * sizeof(char)
);
strncpy(myString, "Hello World", 11);
callString(myString);
free(myString);
return 0;
}
static void
callString(char *_string)
{
printf("%s\n", _string);
}
Thanks #Mat too
You have 3 problems:
myString is uninitialized so calling strlen(myString) doesn't make sense. You need to set it to something meaningful before calling strlen
Your malloc call is wrong, you should not allocate strlen(...) * sizeof(char), but rather strlen(...) + 1, since strings in C are null terminated and you must allocate room for the null terminator. Also, to multiply with sizeof(char) isn't necessary since that is guaranteed to be equal to 1.
After you malloc, you can't assign the pointer to something else: myString = "Hello World!";. This is what Valgrind complains about, it is a memory leak. Strings are copied using strcpy, not with = assignment.
Also, it is good practice to free() all memory at the end of the program.

malloc doesn't look to work in my program

I have a function which prints the whole content of the file and the function seems to work fine, but valgring complains about Conditional jump or move depends on uninitialised value(s) and Uninitialised value was created by a heap allocation:
==7876== Memcheck, a memory error detector
==7876== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7876== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7876== Command: ./program
==7876==
==7876== Conditional jump or move depends on uninitialised value(s)
==7876== at 0x4E864B2: vfprintf (vfprintf.c:1642)
==7876== by 0x4E8CC38: printf (printf.c:33)
==7876== by 0x40074C: main (program.c:45)
==7876== Uninitialised value was created by a heap allocation
==7876== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7876== by 0x4008A7: printFile (program.c:23)
==7876== by 0x40073A: main (program.c:43)
==7876==
The world is not enought and michi is the only one who's not agree.
==7876==
==7876== HEAP SUMMARY:
==7876== in use at exit: 0 bytes in 0 blocks
==7876== total heap usage: 2 allocs, 2 frees, 621 bytes allocated
==7876==
==7876== All heap blocks were freed -- no leaks are possible
==7876==
==7876== For counts of detected and suppressed errors, rerun with: -v
==7876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Here is the program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *printFile(char *fileName){
size_t length=0,size=0;
char *buffer;
FILE *file;
file = fopen (fileName , "r" );
if (file==NULL){
printf("\n");
printf("\tThe file %s does not Exists\n", fileName);
exit(1);
}
fseek (file , 0 , SEEK_END);
length = (size_t)ftell (file);
fseek (file , 0 , SEEK_SET);
buffer = malloc(length+1);
if (!buffer){
fputs ("Memory error",stderr);
exit (2);
}
size = fread (buffer,1,length+1,file);
if (size != length){
fputs ("Reading error",stderr);
exit(3);
}
fclose (file);
return buffer;
}
int main (void) {
char *fileName = "test.txt";
char *fileContent = printFile(fileName);
printf("%s",fileContent);
free(fileContent);
return 0;
}
A quick fix is to use calloc instead of malloc, because it zeros the returned bytes
So I replaced:
buffer = malloc(length+1);
with:
buffer = calloc(length,sizeof(char*));
And valgrind doesn't complain:
==7897== Memcheck, a memory error detector
==7897== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7897== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7897== Command: ./program
==7897==
The world is not enought and michi is the only one who's not agree.
==7897==
==7897== HEAP SUMMARY:
==7897== in use at exit: 0 bytes in 0 blocks
==7897== total heap usage: 2 allocs, 2 frees, 1,096 bytes allocated
==7897==
==7897== All heap blocks were freed -- no leaks are possible
==7897==
==7897== For counts of detected and suppressed errors, rerun with: -v
==7897== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
My question is, why does malloc produce that error and how to avoid calloc.
Do I have some codding problem here or is just malloc?
.
.
EDIT:
if I change:
size = fread (buffer,1,length+1,file);
with:
size = fread (buffer,1,length,file);
I get:
==7985== Memcheck, a memory error detector
==7985== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7985== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7985== Command: ./program
==7985==
==7985== Invalid read of size 1
==7985== at 0x4E864B2: vfprintf (vfprintf.c:1642)
==7985== by 0x4E8CC38: printf (printf.c:33)
==7985== by 0x40074C: main (program.c:44)
==7985== Address 0x52022f4 is 0 bytes after a block of size 68 alloc'd
==7985== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7985== by 0x4008A6: printFile (program.c:22)
==7985== by 0x40073A: main (program.c:42)
==7985==
The world is not enought and michi is the only one who's not agree.
==7985==
==7985== HEAP SUMMARY:
==7985== in use at exit: 0 bytes in 0 blocks
==7985== total heap usage: 2 allocs, 2 frees, 620 bytes allocated
==7985==
==7985== All heap blocks were freed -- no leaks are possible
==7985==
==7985== For counts of detected and suppressed errors, rerun with: -v
==7985== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
You print the file content read into your buffer but nothing can ensure that the buffer contains a NUL char, so valgrind complains because printf parse your data until NUL (jump or move depends on uninitialised value(s)). Using calloc tells valgrind that you are more precautious...
Your string must be NUL-terminated. Without it, the program has undefined behaviour, which valgrind rightfully reports.
The easiest way to NUL-terminate the string is:
size = fread (buffer,1,length,file); /* no need to specify useless extra char */
/* it will never be read */
... /* check for errors here */
buffer[length] = '\0'; /* <--- null termination */
calloc fills the entire buffer with NUL characters, but it's a waste of cycles. You only need one.
Memory obtained via malloc() is uninitialized. That's intentional. The workarounds are to use calloc() instead or to initialize that memory obtained via malloc() before you read from it. Under some circumstances you can initialize only part of it, and often you have better initial values available than all zeroes.
Your particular error is only peripherally related to that, however. You do initialize most of the buffer, via fread(), but you allocate one more byte than the file is long, and fread() does not store anything in that last byte. It looks like maybe you intended to add a '\0' terminator, but forgot. It's that last byte that valgrind complains about.
In this case, the memory-clearing performed by calloc() mostly serves no purpose, as you are about to overwrite all bytes in the buffer but one. But it does initialize that last byte, too, which turns out to save you several kinds of trouble when you fail to initialize it any other way.

wchar_t valgrind issue - Invalid read of size 8

I'm not able to figure out why Valgrind is printing Invalid read of size 8 when using wchar_t. I'm running a 64bit Ubuntu (3.5.0-25) system with valgrind-3.7.0 and gcc 4.7.2.
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// const wchar_t *text = L"This is a t"; // no Valgrind error
// const wchar_t *text = L"This is a teeeeeeee"; // no Valgrind error
const wchar_t *text = L"This is a test"; // Valgrind ERRROR
wchar_t *new_text = NULL;
new_text = (wchar_t*) malloc( (wcslen(text) + 1) * sizeof(wchar_t));
wcsncpy(new_text, text, wcslen(text));
new_text[wcslen(text)] = L'\0';
printf("new_text: %ls\n", new_text);
free(new_text);
return 0;
}
Compile:
$ gcc -g -std=c99 test.c -o test
$ valgrind --tool=memcheck --leak-check=full --track-origins=yes --show-reachable=yes ./test
Valgrind results:
==19495== Memcheck, a memory error detector
==19495== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==19495== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==19495== Command: ./test
==19495==
==19495== Invalid read of size 8
==19495== at 0x4ED45A7: wcslen (wcslen.S:55)
==19495== by 0x4ED5C0E: wcsrtombs (wcsrtombs.c:74)
==19495== by 0x4E7D160: vfprintf (vfprintf.c:1630)
==19495== by 0x4E858D8: printf (printf.c:35)
==19495== by 0x4006CC: main (test.c:16)
==19495== Address 0x51f1078 is 56 bytes inside a block of size 60 alloc'd
==19495== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19495== by 0x40066F: main (test.c:12)
==19495==
new_text: This is a test
==19495==
==19495== HEAP SUMMARY:
==19495== in use at exit: 0 bytes in 0 blocks
==19495== total heap usage: 1 allocs, 1 frees, 60 bytes allocated
==19495==
==19495== All heap blocks were freed -- no leaks are possible
==19495==
==19495== For counts of detected and suppressed errors, rerun with: -v
==19495== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
Now if I run the same but with a 'working string', let's say
const wchar_t *text = L"This is a t"; // no Valgrind error
// const wchar_t *text = L"This is a teeeeeeee"; // no Valgrind error
// const wchar_t *text = L"This is a test"; // Valgrind ERRROR
I get no issue:
==19571== Memcheck, a memory error detector
==19571== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==19571== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==19571== Command: ./test
==19571==
new_text: This is a t
==19571==
==19571== HEAP SUMMARY:
==19571== in use at exit: 0 bytes in 0 blocks
==19571== total heap usage: 1 allocs, 1 frees, 48 bytes allocated
==19571==
==19571== All heap blocks were freed -- no leaks are possible
==19571==
==19571== For counts of detected and suppressed errors, rerun with: -v
==19571== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
At first I thought the string size should be always be multiple of 8 (maybe some wcs read chunks of 8) but some cases failed, then I thought I'd have to append always 8 bytes for the NULL terminator ((wcslen(item) + 2) * sizeof(wchar_t)), it worked but that doesn't make any sense since sizeof(wchar_t) - in my system - is 4 bytes and should be enough to handle the L'\0' terminator.
I also read the glibc wcslen source code but nothing new. I'm now thinking of Valgrind issue. Do you guys could throw some light here? Does it worth to file a bug against Valgrind?
Thank you
This is probably caused by SSE optimisation of the wcslen function; see e.g. https://bugzilla.redhat.com/show_bug.cgi?id=798968 or https://bugs.archlinux.org/task/30643.
When optimising wcslen, it's faster to read multiple wide characters at a time and use vectorised instructions (SSE) to compare them to L'\0'. Unfortunately valgrind sees this as an uninitialised read - which it is, but it's harmless because the result of wcslen does not depend on the uninitialised value.
The fix is to update valgrind in the hope that a newer version will suppress the false positive.

How do I identify which values values are uninitialised in valgrind?

This might seem like a silly question but valgrind doesn't by default give you quite enough information. Valgrind reports the following:
==2541== Conditional jump or move depends on uninitialised value(s)
==2541== at 0x401777: process_read.clone.3 (in /home/matt/dev/ocs/client3/a.out)
==2541== by 0x4026B8: obbs_main (in /home/matt/dev/ocs/client3/client)
==2541== by 0x53D1D8B: start_thread (pthread_create.c:304)
==2541== by 0x511D04C: clone (clone.S:112)
I can't see anything obvious. Valgrind -v also doesn't help.
Is there a way to get valgrind to tell me which values are uninitialsed?
If you use the --track-origins=yes flag with valgrind it will tell you the line number (assuming you compiled with -g) where the unitialized memory was first allocated. This is usually at the stack allocation at the beginning of a function somewhere.
Try compiling with -Wall as well. -Wall should catch most "used uninitialized" errors at compile time.
Valgrind notifies you about use of uninitialized values - not just uninitialized values eg:
==1029== Memcheck, a memory error detector
==1029== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==1029== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==1029== Command: a.out
==1029==
==1029== Conditional jump or move depends on uninitialised value(s)
==1029== at 0x4004D7: main (uninit.c:6)
==1029==
==1029==
==1029== HEAP SUMMARY:
==1029== in use at exit: 0 bytes in 0 blocks
==1029== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==1029==
==1029== All heap blocks were freed -- no leaks are possible
==1029==
==1029== For counts of detected and suppressed errors, rerun with: -v
==1029== Use --track-origins=yes to see where uninitialised values come from
==1029== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
[adrian#iceweasel ~]$ cat uninit.c
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
if(i)
{
printf("Hello\n");
}
return 0;
}

Resources