I have installed Clang in my machine (ubuntu) in order to find memory leaks in my C code. I wrote a sample code in order to check the working of it which is as follows:
/* File: hello.c for leak detection */
#include <stdio.h>
#include <stdlib.h>
void *x;
int main() {
x = malloc(2);
x = 0; // Memory leak
return 0;
}
I found some options in internet to compile like
$ scan-build clang --analyze hello.c
and
$ scan-build clang -fsanitize=address hello.c
But none of them are showing any signs of memory leak.
scan-build: Using '/usr/bin/clang' for static analysis scan-build:
Removing directory '/tmp/scan-build-2015-07-02-122717-16928-1' because
it contains no reports. scan-build: No bugs found.
Can anyone kindly tell how to correctly use Clang for Memory leak detection.
Interestingly, the clang static analyzer finds the memory leak if you declare void *x inside main:
int main() {
void *x = malloc(2);
x = 0; // Memory leak
return 0;
}
Analyzing this code by running:
scan-build clang -g hello.c
gives a warning like:
hello.c:9:3: warning: Potential leak of memory pointed to by 'x'
return 0;
^~~~~~~~
Related
I ran this C code in CLion and Cygwin toolchain (gcc and gdb) in windows, I tried writing to str[5] which is not allocated:
#include <stdio.h>
#include "stdlib.h"
int main() {
char * str = malloc(4);
str[5] = 'a';
printf("%c\n", str[5]);
return 0;
}
However, it ran without any errors (I was excpecting to get memory access violation and a warning that I didn't free the allocated pointer).
This is how the CMakeLists.txt is configured (I just added the CMAKE_C_FLAGS line):
cmake_minimum_required(VERSION 3.17)
project(myproject C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
add_executable(myproject main.c)
Why didn't it throw warning / error for that memory access? How can I fix that?
You are not allowed to access unallocated memory. At the same time your compiler/runtime is not required to prevent you from doing so.
There is no hand holding in C, you are allowed to shoot yourself in the foot if you so desire.
I'm scratching my head trying to figure out why ASAN isn't picking up on a simple memory leak. valgrind finds it just fine. Help?
Example that ASAN does find.
#include <stdlib.h>
#include <stdio.h>
void blah(void)
{
int *some_int = malloc(sizeof(int));
*some_int = 1;
printf("hello %p\n", some_int);
// some_int is lost here
}
int main()
{
blah();
return 0;
}
mbryan#remotedev-mbryan:~/git/mbryan/onefs$ clang -fsanitize=address -O0 q.c
mbryan#remotedev-mbryan:~/git/mbryan/onefs$ ./a.out
hello 0x602000000010
=================================================================
==10751==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x4d9bd0 in malloc (/ifs/home/mbryan/git/mbryan/onefs/a.out+0x4d9bd0)
#1 0x5120f3 in blah (/ifs/home/mbryan/git/mbryan/onefs/a.out+0x5120f3)
#2 0x512183 in main (/ifs/home/mbryan/git/mbryan/onefs/a.out+0x512183)
#3 0x7f3515000b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).
So far so good. Now print the value instead of the pointer:
#include <stdlib.h>
#include <stdio.h>
void blah(void)
{
int *some_int = malloc(sizeof(int));
*some_int = 1;
printf("hello %d\n", *some_int); // <---------------
}
int main()
{
blah();
return 0;
}
mbryan#remotedev-mbryan:~/git/mbryan/onefs$ clang -fsanitize=address -O0 q.c
mbryan#remotedev-mbryan:~/git/mbryan/onefs$ ./a.out
hello 1
...now the leak doesn't show up.
On the latter if I recompile without the sanitizer and run valgrind, valgrind does indeed show a leak:
==10782== definitely lost: 4 bytes in 1 blocks
Looking at the assembly: I see the optimimzer hasn't made my malloc'd variable a local or some other trickery. So: why isn't AddressSanitizer picking up this one? Am I missing something obvious?
This is on Ubuntu18.04 using clang 6.0.0-1ubuntu2.
I've been informed from the ASAN folks that this is a known bug:
https://github.com/google/sanitizers/issues/937
LeakSanitizer: false negative when functions stack frames overlay #937
I am using gcc 5.1.0 on Windows.
When calling memset I am receiving a SEGFAULT, which does not occur when -flto flag (link time optimisation) is enabled.
/*#### function.h ####*/
void secure_bzero (void *s,size_t size);
/*##### function.c ####*/
/* Securely erase size bytes from s */
void WEAK __attribute__((noinline)) secure_bzero (void *s,size_t size) {
memset(s,0,size);
}
I noticed the segmentation fault, when I wanted to debug my application in CodeBlocks. I enabled the debugging symbols flag (-g) and got warned that Combining -flto with -g is "currently experimental and expected to produce wrong results."
I don't understand how the segmentation fault is produced here.
thanks to Eugene Sh. hint to post a complete example:
#include "function.h"
int main(){
unsigned char seed[32];
for (int i=0; i<32; i++){
seed[i] = i;
}
secure_bzero(seed,sizeof(seed));
return 1;
}
I recoded malloc free and realloc in c using mmap and munmap. I compiled them as a shared library .so file.
Here is a simple test:
#include <stdlib.h>
int main() {
int i;
char *addr;
i = 0;
while (i < 1024)
{
addr = (char*)malloc(1024);
addr[0] = 42;
i++;
}
return (0);
}
Here is a run.sh that must replace the stdlib by my shared library:
#/bin/sh
export DYLD_LIBRARY_PATH=.
export DYLD_INSERT_LIBRARIES="libft_malloc.so"
export DYLD_FORCE_FLAT_NAMESPACE=1
$#
The problem is that when i am compiling directly the test file with my shared library and replacing the header in it, it is working well:
-> gcc test1.c libft_malloc.so
-> ./a.out
-> no error
But when i am running it with the run.sh that should just replace the official malloc library by my libft_malloc.so file, i am getting a segfault:
-> gcc test1.c
-> ./run.sh ./a.out
-> ./run.sh: line 5: 73502 Segmentation fault: 11 $#
I know the error is in my code and not in the run.sh or in the test.c because they are the officials files i must use to test my library in my school and those files are working well on other malloc repositories, but i can't find what can be the problem.
Here is my repository: https://github.com/Shirakawa42/malloc.git
I tried debugged by placing write() everywhere but the segfault don't seems to be in the malloc, so i'm lost.
edit:
It also segfault if we run a test without any malloc, but just by loading my library:
#include <stdlib.h>
int main() {
int i;
i = 0;
while (i < 1024)
{
i++;
}
return (0);
}
-> gcc test1.c
-> ./run.sh ./a.out
-> ./run.sh: line 5: 74764 Segmentation fault: 11 $#
edit 2:
Compiling with flag fsanitize=address repair the segfault, but it's absolutely not optimal
edit 3:
Setting the 2 first export manually in shell tell me:
dyld: warning: could not load inserted library 'libft_malloc.so' into library validated process because no suitable image found. Did find:
libft_malloc.so: code signing blocked mmap() of 'libft_malloc.so'
and after setting the third export all my actions make me segfault, like ls and vim, cd made me abort
dyld: warning: could not load inserted library 'libft_malloc.so' into library validated process because no suitable image found. Did find:
libft_malloc.so: code signing blocked mmap() of 'libft_malloc.so'
This error append when there are a segfault in your malloc or free, repairing free made it work.
You can debug it in gdb. First build your code with debug options:
gcc -g -O0
Above options should be used for both your lib and test program. Then you can try running you program in gdb:
gdb a.out
(gdb) r <arguments to a.out>
(gdb) bt <-- when it crashes
Linux loads you program in the memory and calls the entry point main. Startup code that compiler adds for the platform may have calls to malloc. Hence, the crash without malloc in your test code.
I was compiling this program and the compilation went fine. The moment I executed it, it failed with free(): invalid pointer error.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = NULL;
if ((p = (char *) malloc((int)sizeof(char) * 100)) == NULL) {
printf("ERROR: unable to allocate memory\n");
return -1;
}
p += 50;
free(p);
return 0;
}
I compiled using gcc -o memtest m.c command.
Are there any GCC compiler options that will give a warning/error/indication about these invalid pointer errors during compile time?
No. Use Electric Fence or Valgrind.
compile time no, runtime - yes: http://gcc.gnu.org/wiki/Mudflap_Pointer_Debugging
The closest you may get for compile time is: http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html
No, such errors aren't detected at compile-time because in practice such detection would only trigger for the most trivial cases, like your example.