I want to use LeakSanitizer to detect leaked memory, but the style of the program I am using does not free memory before exit. This is fairly common in my experience.
I want to detect this leak:
int main(int argc, char const *argv[])
{
char *p = malloc(5);
p = 0;
return 0;
}
And ignore this leak:
int main(int argc, char const *argv[])
{
char *p = malloc(5);
return 0;
}
You want LSan to report only unreachable leaks i.e. pointers which are guaranteed to be leaked by the program. Problem is that by default LeakSanitizer runs it's checks at the end of the program, often after global C++ dtors have completed and their contents is no longer considered accessible. So when LSan finally runs, it has to assume that lots of stuff is no longer reachable. To work around this issue you can add
#include <lsan_interface.h>
...
#ifdef __SANITIZE_ADDRESS__
__lsan_do_leak_check();
__lsan_disable();
#endif
before returning from main (inspired by Issue 719 and llvm discussion).
PS: Be careful with extremely simple examples like the ones you post above. GCC will often remove unused assignments and allocations even at -O0 so always check that assembler matches your expectations.
Related
I am using clang static analysis under Xcode 6.4 (6E35b), and getting a false positive warning about a potential memory leak. I do explicitly free the memory in question, but the freeing happens in a different compilation unit. Here is my MWE:
file2.c: Performs the actual freeing.
#include <stdlib.h>
void my_free(const void* p) {
free((void*) p);
}
file1.c: Allocates memory and explicitly frees it through an external function.
#include <stdlib.h>
void my_free(const void* p);
int main(int argc, char* argv[]) {
void* data = malloc(1);
if(data) my_free(data);
return 0; /* <-- "Potential leak of memory pointed to by 'data'" */
}
When I define my_free() in the same compilation unit as its invocation, no warning is generated, but of course I need to invoke my_free() from a large number of different source files.
I have read through FAQ and How to Deal with Common False Positives, but it does not address my situation. What can I do to assure clang that I really am freeing the memory in question?
In case the version information is relevant:
% clang --version
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
One way to fix that would be to add code specific for the analyser, in your header file:
#ifdef __clang_analyzer__
#define my_free free
#endif
This will make the static analyser think you're using the classic free function and stop complaining.
In debugging a memory leak on a large project, I found that the source of the leak seemed to be some flex/bison-generated code. I was able to recreate the leak with the following minimal example consisting of two files, sand.l and sand.y:
in sand.l:
%{
#include <stdlib.h>
#include "sand.tab.h"
%}
%%
[0-9]+ { return INT; }
. ;
%%
in sand.y:
%{
#include <stdio.h>
#include <stdlib.h>
int yylex();
int yyparse();
FILE* yyin;
void yyerror(const char* s);
%}
%token INT
%%
program:
program INT { puts("Found integer"); }
|
;
%%
int main(int argc, char* argv[]) {
yyin = stdin;
do {
yyparse();
} while (!feof(yyin));
return 0;
}
void yyerror(const char* s) {
puts(s);
}
The code was compiled with
$ bison -d sand.y
$ flex sand.l
$ gcc -g lex.yy.c sand.tab.c -o main -lfl
Running the program with valgrind gave the following error:
8 bytes in 1 blocks are still reachable in loss record 1 of 3
at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
by 0x40260F: yyalloc (lex.yy.c:1723)
by 0x402126: yyensure_buffer_stack (lex.yy.c:1423)
by 0x400B89: yylex (lex.yy.c:669)
by 0x402975: yyparse (sand.tab.c:1114)
by 0x402EC4: main (sand.y:24)
64 bytes in 1 blocks are still reachable in loss record 2 of 3
at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
by 0x40260F: yyalloc (lex.yy.c:1723)
by 0x401CBF: yy_create_buffer (lex.yy.c:1258)
by 0x400BB3: yylex (lex.yy.c:671)
by 0x402975: yyparse (sand.tab.c:1114)
by 0x402EC4: main (sand.y:24)
16,386 bytes in 1 blocks are still reachable in loss record 3 of 3
at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
by 0x40260F: yyalloc (lex.yy.c:1723)
by 0x401CF6: yy_create_buffer (lex.yy.c:1267)
by 0x400BB3: yylex (lex.yy.c:671)
by 0x402975: yyparse (sand.tab.c:1114)
by 0x402EC4: main (sand.y:24)
It seems that bison and/or flex is holding on to a substantial amount of memory. Is there anyway to force them to free it?
The default flex skeleton allocates an input buffer and a small buffer stack, which it never frees. You could free the input buffer manually with yy_delete_buffer(YY_CURRENT_BUFFER); but there is no documented way to delete the buffer stack. If you have a sufficiently non-ancient version of flex [see Note 1], you can call yylex_destroy() to remove the last vestiges of the buffer stack. (If you don't, it's only 8 bytes in your application, so it's not a disaster.)
If you want to write a clean application, you should generate a reentrant scanner, which puts all persistent data into a scanner context object. Your code must allocate and free this object, and freeing it will free all memory allocations. (You might also want to generate a pure parser, which works roughly the same way.)
However, the reentrant scanner has a very different API, so you will need to get your parser to pass through the scanner context object. If you use a reentrant (pure) parser as well, you'll need to modify your scanner actions because with the reentrant parser, yylval is a YYSTYPE* instead of YYSTYPE.
Notes:
In fact, you can delete the buffer stack using yylex_destroy(), as recently pointed out in a comment, as long as your flex version is at least 2.5.9. Since that version was released almost two decades ago, you'd think this note would be unnecessary, but unfortunately v2.5.4 continues to be the default MinGW installation and it had a surprisingly long life on various Linux distros as well (although I think these days you're not so likely to find it installed).
Does it analysis the lifecycle of the variable and simply insert the cleanup function call at the right place? Does it have any overhead cost?
I've written two pieces of simple code to compare the performance, and compiled them without optimization.
code1:
#include <stdio.h>
#include <stdlib.h>
void clean_up(int **final_value)
{
free(*final_value);
}
int main(int argc, char **argv)
{
for (int i = 0; i < 10000000; i++) {
int *avar = malloc(sizeof(int));
clean_up(&avar);
}
return 0;
}
code2:
#include <stdio.h>
#include <stdlib.h>
void clean_up(int **final_value)
{
free(*final_value);
}
int main(int argc, char **argv)
{
for (int i = 0; i < 10000000; i++) {
int *avar __attribute__ ((__cleanup__(clean_up))) = malloc(sizeof(int));
}
return 0;
}
And their performance are quite similar.
You'll better compile with some optimization, in particular if you want to look into the generated assembler code (compile with gcc -S -fverbose-asm -O)
The intuition behind __attribute__((cleanup)) is that GCC is in fact a compiler for all of C, C++, Ada, Fortran, Go.... That attribute is forcing the same internal representation than for C++ destructors of local variables. The cleanup happens at end of current block scope (e.g. at closing brace } of the block). So the compiler is transforming your code2 with cleanup into the equivalent of code1.
The thing for destructors of global or static variables (which are run after main has returned) is __attribute__((destructor)) on functions (which are also run at dlclose time for plugins).
So to understand these attributes, you'll better think in C++ terms.
My opinion is that if you need these cleanup attributes, you should code your thing in C++ not in C. Your code would be much more readable and less compiler dependent. I feel that cleanup is in practice only useful in generated C code. I never used it (and feel that when I need it, I should switch to C++).
The cleanup function is called when the variable goes out of scope. It doesn't care, whether this would leave other pointers dangling.
i have this function:
char code[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f";
int main(int argc, char **argv)
{
int (*func)();
func = (int (*)()) code;
(int)(*func)();
}
(this code is from: shellcode tutorial)
so i compiled and execute it, but i only get this message: Speicherzugriffsfehler (Speicherabzug geschrieben).
Why i don't get something back, only this error message?
p.s.: my system is an ubuntu x86 pc. the shellcode should work with it. i compiled it with gcc and with gcc-4.5, both same error...
Your code variable is an array that's part of your program's initialized data (.data) segment. When your program is loaded by the OS, the loader reads and executes the load commands from your executable file. One of those commands is "load the following data (a segment named .data) into memory".
Ordinarily, the .data segment is loaded as a non-executable segment, meaning that the memory there cannot be executed. Therefore, if you try to execute code from there by jumping to it, like you did, then it will crash with a segmentation fault.
There are a couple of ways to work around this. You can tell the linker to make the .data segment executable (not a good idea). You can tell the compiler to put the code variable into the .text segment instead (the segment used for all of your program's regular code). You can tell the compiler and linker to make a new executable segment and put code into that. All of these are tricky.
The best solution, is to specifically allocate your own executable memory at runtime and copy the shellcode into that. That completely avoids any potential compiler/linker issues, although it does add a small runtime penalty. But some OSes don't allow memory to be both writable and executable at the same time; so you'd first have to make it writable, copy the shellcode in, and then make it executable.
The way you control memory permissions at runtime is with the mprotect(2) call. So here's a good way to do it:
#include <string.h>
#include <sys/mman.h>
char shellcode[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f";
// Error checking omitted for expository purposes
int main(int argc, char **argv)
{
// Allocate some read-write memory
void *mem = mmap(0, sizeof(shellcode), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
// Copy the shellcode into the new memory
memcpy(mem, shellcode, sizeof(shellcode));
// Make the memory read-execute
mprotect(mem, sizeof(shellcode), PROT_READ|PROT_EXEC);
// Call the shellcode
int (*func)();
func = (int (*)())mem;
(int)(*func)();
// Now, if we managed to return here, it would be prudent to clean up the memory:
munmap(mem, sizeof(shellcode));
return 0;
}
By default gcc will compile applications as having nonexecutable stacks. What you're seeing is a segmentation violation because your stack is marked nonexecutable but you're trying to execute code on the stack. You can verify by running your application in gdb and checking where it dies, for instance:
=> 0x601060 : jmp 0x60107b
This is the entry point of your shellcode. To make it so it doesn't segfault, you can disable exectstack by doing the following:
gcc -z execstack source.c
I have seen a strange behavior with "strndup" call on AIX 5.3 and 6.1.
If I call strndup with size more than the size of actual source string length, then there is a stack corruption after that call.
Following is the sample code where this issue can come:
int main ()
{
char *dst_str = NULL;
char src_str[1023] = "sample string";
dst_str = strndup(src_str, sizeof(src_str));
free(dst_str);
return 0;
}
Does anybody have experienced this behavior?
If yes please let me know.
As per my observation, there must be a patch from OS where this issue got fixed. but i could not get that patch if at all there is any. Please throw some light.
Thanks & Regards,
Thumbeti
You are missing a #include <string.h> in your code. Please try that—I am fairly sure it will work. The reason is that without the #include <string.h>, there is no prototype for strndup() in scope, so the compiler assumes that strndup() returns an int, and takes an unspecified number of parameters. That is obviously wrong. (I am assuming you're compiling in POSIX compliant mode, so strndup() is available to you.)
For this reason, it is always useful to compile code with warnings enabled.
If your problem persists even after the change, there might be a bug.
Edit: Looks like there might be a problem with strndup() on AIX: the problem seems to be in a broken strnlen() function on AIX. If, even after #include <string.h> you see the problem, it is likely you're seeing the bug. A google search shows a long list of results about it.
Edit 2:
Can you please try the following program and post the results?
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *test1 = "abcdefghijabcdefghijabcdefghijk";
char *test2 = "012345678901234567890123456789";
char *control = "01234567890123456789012345678";
char *verify;
free(strndup(test1, 30));
verify = strndup(test2, 29); /* shorter then first strndup !!! */
fprintf(stderr,">%s<\n",verify);
if (strcmp(control, verify))
printf("strndup is broken\n");
}
(Taken from https://bugzilla.samba.org/show_bug.cgi?id=1097#c10.)
Edit 3: After seeing your output, which is >01234567890123456789012345678<, and with no strndup is broken, I don't think your version of AIX has the strndup bug.
Most likely you are corrupting memory somewhere (given the fact that the problem only appears in a large program, under certain conditions). Can you make a small, complete, compilable example that exhibits the stack corruption problem? Otherwise, you will have to debug your memory allocation/deallocation in your program. There are many programs to help you do that, such as valgrind, glibc mcheck, dmalloc, electricfence, etc.
Old topic, but I have experienced this issue as well. A simple test program on AIX 6.1, in conjunction with AIX's MALLOCDEBUG confirms the issue.
#include <string.h>
int main(void)
{
char test[32] = "1234";
char *newbuf = NULL;
newbuf = strndup(test, sizeof(test)-1);
}
Compile and run the program with buffer overflow detection:
~$ gcc -g test_strndup2.c
~$ MALLOCDEBUG=catch_overflow ./a.out
Segmentation fault (core dumped)
Now run dbx to analyze the core:
~$ dbx ./a.out /var/Corefiles/core.6225952.22190412
Type 'help' for help.
[using memory image in /var/Corefiles/core.6225952.22190412]
reading symbolic information ...
Segmentation fault in strncpy at 0xd0139efc
0xd0139efc (strncpy+0xdc) 9cc50001 stbu r6,0x1(r5)
(dbx) where
strncpy() at 0xd0139efc
strndup#AF5_3(??, ??) at 0xd03f3f34
main(), line 8 in "test_strndup2.c"
Tracing through the instructions in strndup, it appears that it mallocs a buffer that is just large enough to handle the string in s plus a NULL terminator. However, it will always copy n characters to the new buffer, padding with zeros if necessary, causing a buffer overflow if strlen(s) < n.
char* strndup(const char*s, size_t n)
{
char* newbuf = (char*)malloc(strnlen(s, n) + 1);
strncpy(newbuf, s, n-1);
return newbuf;
}
Alok is right. and with the gcc toolchain under glibc, you would need to define _GNU_SOURCE to get the decl of strndup, otherwise it's not decl'd, e.g.:
#include <string.h>
...
compilo:
gcc -D_GNU_SOURCE a.c
Thanks a lot for your prompt responses.
I have tried the given program.
following is the result:
bash-2.05b# ./mystrndup3
>01234567890123456789012345678<
In my program I have included , still problem is persistent.
Following is the strndup declaration in prepossessed code.
extern char * strndup(const char *, size_t);
I would like to clarify one thing, with small program I don't get effect of stack corruption. It is consistently appearing in my product which has huge amount of function calls.
Using strndup in the following way solved the problem:
dst_str = strndup(src_str, srtlen(src_str));
Please note: used strlen instead of sizeof as i need only the valid string.
I am trying to understand why it is happening.
Behavior i am seeing with my product when i use strndup with large size:
At the "exit" of main, execution is coring with "illegal instruction"
intermittently "Illegal Instruction" in the middle of execution (after strndup call).
Corrupt of some allocated memory, which is no where related to strndup.
All these issues are resolved by just modifying the usage of strndup with actual size of source string.
Thanks & Regards,
Thumbeti