Double-Free exercise doesn't act as expected - c

I am reading the book "Effective C" by Robert C. Seacord.
In this book, it has an exercise where you intentionally double-free a pointer so you can test using dmalloc to debug the cause. However, it doesn't fail as expected.
#include <string.h>
#include <stdlib.h>
#ifdef DMALLOC
#include "dmalloc.h"
#endif
void usage(char *msg) {
fprintf(stderr, "%s", msg);
free(msg);
return;
}
int main(int argc, char *argv[]) {
if (argc != 3 && argc !=4) {
/* The error message won't be more than 80 chars */
char *errmsg = (char *)malloc(80);
sprintf(
errmsg,
"Sorry %s,\nUsage: caesar secret_file keys_file [output_file]\n",
getenv("USER")
);
usage(errmsg);
free(errmsg);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
Its clear here that *errmsg should get freed twice:
First by the usage function when its passed to it, and then right after in main.
Why doesn't this fail when ran with no arguments? I am using linux (POP!_OS 20.04) with GCC 9.3.0.
EDIT: For more context the book suggests I should see an output like this:
% ./caesar
Sorry student,
Usage: caesar secret_file keys_file [output_file]
debug-malloc library: dumping program, fatal error
Error: tried to free previously freed pointer (err 61)
Aborted (core dumped)
Adding more calls to free doesn't do anything either.
I get the usage portion but not a core dump.

I am sorry for taking up people's time with this. I figured it out.
That crash behavior is supposed to be provided by dmalloc, however its usage has changed a little since the writing of the book I am reading.
I needed to add -DDMALLOC_FUNC_CHECK to the compiler options in order for it to produce the expected result.
I learned its dmalloc, not the OS that causes the program to crash when you double-free the pointer.

Related

A question about allocating memory : C [UBUNTU]

I'm currently doing an exercise where I have to create a program that takes all the code that is written inside it, and outputs it to the screen when the program is executed.
The exercise suggests that we may find it appropriate to change the file names of the program in the future - and assuming that the renaming is done in a coordinated manner, i.e. the source file and the execution file are given the same new name (except for the extension), the program should work correctly, without the need for any changes to the source code, and without the need to recompile.
The C program itself is called 'prnt.c'-
I wrote the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENDFILEC ".c" /* extension */
int main(int argc, char *argv[])
{
FILE *filePointer;
int character;
char *fileNameToOpen;
fileNameToOpen = (char *)malloc(strlen(argv[0]) + 3); /* allocating memory for string + 3 for the extension - '.c' and \0 */
strcpy(fileNameToOpen, argv[0]);
strcat(fileNameToOpen , ENDFILEC); /* ending '.c' in the end */
filePointer = fopen(fileNameToOpen, "r");
while(!feof(filePointer))
{
character = fgetc(filePointer);
printf("%c" , character);
}
fclose(filePointer);
return 0;
}
I made a 'makefile' to compile the program and I made it so that the executable would be called 'prnt1'.
basically, like the following:
prnt1 : prnt.c
gcc -ansi -Wall -pedantic prnt.c -o prnt1
The compilation worked, but whenever I run the program itself, it gives me a runtime error, saying: "Segmentation fault (core dumped)". When I look at the code itself, I don't seem to reach a memory that doesn't belong to me, so what could be an explanation for that problem and what can be done about it? Thank you in advance for your help.
Since you said that the executable is named "prnt1" and the source file (which you want to read the code from) is named "prnt", argv[0] has the name of the executable (i.e. "prnt1") and, when ".c" is appended to argv[0], it becomes "prnt1.c" – which is definitely not the file you are trying to read from; athen, since this file doesn't exist, you're getting a segmentation fault.
So, as Tom Karzes said, always check the return value of fopen().

Library interpositioning

I have been trying to intercept calls to malloc and free, following our textbook (CSAPP book).
I have followed their exact code, and nearly the same code that I found online and I keep getting a segmentation fault. I heard our professor saying something about printf that mallocs and frees memory so I think that this happens because I am intercepting a malloc and since I am using a printf function inside the intercepting function, it will call itself recursively.
However I can't seem to find a solution to solving this problem? Our professor demonstrated that intercepting worked ( he didn't show us the code) and prints our information every time a malloc occurs, so I do know that it's possible.
Can anyone suggest a working method??
Here is the code that I used and get nothing:
mymalloc.c
#ifdef RUNTIME
// Run-time interposition of malloc and free based on // dynamic linker's (ld-linux.so) LD_PRELOAD mechanism #define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h> #include <dlfcn.h>
void *malloc(size_t size) {
static void *(*mallocp)(size_t size) = NULL; char *error;
void *ptr;
// get address of libc malloc
if (!mallocp) {
mallocp = dlsym(RTLD_NEXT, "malloc"); if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(EXIT_FAILURE);
}
}
ptr = mallocp(size);
printf("malloc(%d) = %p\n", (int)size, ptr); return ptr;
}
#endif
test.c
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("main\n");
int* a = malloc(sizeof(int)*5);
a[0] = 1;
printf("end\n");
}
The result i'm getting:
$ gcc -o test test.c
$ gcc -DRUNTIME -shared -fPIC mymalloc.c -o mymalloc.so
$ LD_PRELOAD=./mymalloc.so ./test
Segmentation Fault
This is the code that I tried and got segmentation fault (from https://gist.github.com/iamben/4124829):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void* malloc(size_t size)
{
static void* (*rmalloc)(size_t) = NULL;
void* p = NULL;
// resolve next malloc
if(!rmalloc) rmalloc = dlsym(RTLD_NEXT, "malloc");
// do actual malloc
p = rmalloc(size);
// show statistic
fprintf(stderr, "[MEM | malloc] Allocated: %lu bytes\n", size);
return p;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_LEN 128
int main(int argc, const char *argv[])
{
char *c;
char *str1 = "Hello ";
char *str2 = "World";
//allocate an empty string
c = malloc(STR_LEN * sizeof(char));
c[0] = 0x0;
//and concatenate str{1,2}
strcat(c, str1);
strcat(c, str2);
printf("New str: %s\n", c);
return 0;
}
The makefile from the git repo didn't work so I manually compiled the files and got:
$ gcc -shared -fPIC libint.c -o libint.so
$ gcc -o str str.c
$ LD_PRELOAD=./libint.so ./str
Segmentation fault
I have been doing this for hours and I still get the same incorrect result, despite the fact that I copied textbook code. I would really appreciate any help!!
One way to deal with this is to turn off the printf when your return is called recursively:
static char ACallIsInProgress = 0;
if (!ACallIsInProgress)
{
ACallIsInProgress = 1;
printf("malloc(%d) = %p\n", (int)size, ptr);
ACallIsInProgress = 0;
}
return ptr;
With this, if printf calls malloc, your routine will merely call the actual malloc (via mallocp) and return without causing another printf. You will miss printing information about a call to malloc that the printf does, but that is generally tolerable when interposing is being used to study the general program, not the C library.
If you need to support multithreading, some additional work might be needed.
The printf implementation might allocate a buffer only once, the first time it is used. In that case, you can initialize a flag that turns off the printf similar to the above, call printf once in the main routine (maybe be sure it includes a nice formatting task that causes printf to allocate a buffer, not a plain string), and then set the flag to turn on the printf call and leave it set for the rest of the program.
Another option is for your malloc routine not to use printf at all but to cache data in a buffer to be written later by some other routine or to write raw data to a file using write, with that data interpreted and formatted by a separate program later. Or the raw data could be written by a pipe to a program that formats and prints it and that is not using your interposed malloc.

String token from `strsep` not printing (seg fault)

I'm using with a smaller piece of code to test functionality for a larger (beginner) program, but I have a problem displaying the token I've pulled out of a string.
I found and used:
#include <stdio.h>
#include <string.h>
int main()
{
char *string, *found;
string = strdup ("1/2/3");
printf("Original string: '%s'\n",string);
while ((found = strsep(&string,"/")) != NULL )
printf ("%s\n",found);
return (0);
}
and this works fine, prints the tokens one at a time as strings.
Then when I try and move to a user entered string:
#include <stdio.h>
#include <string.h>
int main()
{
char string[13];
char *found, *cp = string;
fprintf(stderr, "\nEnter string: ");
scanf("%12s",string);
printf("Original string: '%s'\n",string);
while((found = strsep(&cp,"/,-")) != NULL )
printf("Test 1"); /*To pinpoint where the seg fault arises*/
printf("%s\n",found);
return(0);
}
I get a seg fault on the printf("%s\n",found); line. I'm getting the hang of basics of pointers, arrays and strings, but clearly I'm missing something, and would love for someone to tell me what it is!
Also - if I change the argument of printf("%s\n",found); e.g. to printf("%i\n",found); I get some randomness returned, but always the correct amount, e.g. If I enter 1/2/3 I get three lines of junk, entering 1111/2222 gives two lines. I tried %c, %i, %d, %p and they all do the same, but %s seg faults.
I'm completely stumped.
The segfault is because you're missing braces around your while. You'll keep printing "Test 1" until strsep returns NULL, then you try to print that result (and segfault).
With several warning flags (probably -Wall), gcc helps out here:
sep.c:13:3: warning: this ‘while’ clause does not guard... [-Wmisleading-indentation]
while((found = strsep(&cp,"/,-")) != NULL )
^~~~~
sep.c:15:5: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the ‘while’
printf("%s\n",found);
^~~~~~
With braces added around the while, the program works as expected:
./sep
Enter string: abc/def
Original string: 'abc/def'
Test 1abc
Test 1def
This is the problem:
while((found = strsep(&cp,"/,-")) != NULL )
printf("Test 1"); /*To pinpoint where the seg fault arises*/
printf("%s\n",found);
and you think you are doing both printfs inside the loop, but in reality this
code is equivalent to
while((found = strsep(&cp,"/,-")) != NULL )
{
printf("Test 1"); /*To pinpoint where the seg fault arises*/
}
printf("%s\n",found);
that means, printf("%s\n",found); is basically doing printf("%s\n",NULL);
which is undefined behaviour and may cause a segfault.
Note that in C indentation does not matter to the compiler. So you would need to
use { and } around the code:
while((found = strsep(&cp,"/,-")) != NULL )
{
printf("Test 1"); /*To pinpoint where the seg fault arises*/
printf("%s\n",found);
}
Doing that I get
$ ./a
Enter string: aa/bb/cc/dd
Original string: 'aa/bb/cc/dd'
Test 1aa
Test 1bb
Test 1cc
Test 1dd
Also note that your first code is leaking memory, you are not freeing the
allocated memory returned by strdup. You would have to save a pointer to that:
#include <stdio.h>
#include <stdlib.h> // for the free function
#include <string.h>
int main()
{
char *orig = *string, *found;
orig = string = strdup ("1/2/3");
printf("Original string: '%s'\n",string);
while ((found = strsep(&string,"/")) != NULL )
printf ("%s\n",found);
free(orig);
return 0;
}
edit
Neither Stephen Newell nor me seems to have the same problem with the
corrected version of the code. The OP provided a link to onlinegdb.com
showing that the corrected version ends with a segfault.
I tried the same code on ideone.com and I also got the segfault. That seemed
strange to me, so I opened my man page of strsep and found this:
man strsep
SYNOPSIS
#include <string.h>
char *strsep(char **stringp, const char *delim);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
strsep():
Since glibc 2.19:
_DEFAULT_SOURCE
Glibc 2.19 and earlier:
_BSD_SOURCE
The important part is this here: Since glibc 2.19: _DEFAULT_SOURCE
So if you add
#define _DEFAULT_SOURCE
before including any standard C header file, then it works on onlinegdb.com
and ideone.com.
So the code should be:
#define _DEFAULT_SOURCE // <-- important
#include <stdio.h>
#include <string.h>
int main()
{
char string[13];
char *found, *cp = string;
fprintf(stderr, "\nEnter string: ");
scanf("%12s",string);
printf("Original string: '%s'\n",string);
while((found = strsep(&cp,"/,-")) != NULL )
{
printf("Test 1"); /*To pinpoint where the seg fault arises*/
printf("%s\n",found);
}
return(0);
}
See:
corrected onlinegdb.com version
corrected ideone.com version

Detecting a segmention fault in C

I have Win7 Pro (32 bit) and CodeBlocks IDE.
I would like to know is there any way to detect line with a segmention fault in C. My code is PRIME1.c
I find somewhere on Stack Overflow that this is possible on linux in terminal, but I would like to do that in Windows.
Could anyone tell me how to do that?
Many thanks!
In other words, I would like to know how to use debugger from cmd in windows 7 and how it can tell me which line is problematic.
I just found this link
Determine the line of C code that causes a segmentation fault?
But, as you can see, this is for Linux.
I would like to know how can I do that in Windows cmd?
You can catch seg fault. But, unfortunately, can not handle this event anyhow or get any info about that fault (in standard way, there are workarounds specific for compilers). So, maybe put printf in every line with __LINE__ macro and just wait until it fails.
#include <signal.h>
#include <conio.h>
#include <stdio.h>
void listener(int sig) {
printf("listener: access violation");
_getch();
}
void main() {
char a = 10;
char *p = &a;
signal(SIGSEGV, listener);
do {
printf("%d", *p++);
} while (1);
_getch();
}

strndup call is currupting stack frames

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

Resources