realloc printing old contents - pointers

realloc still prints old content even reallocated size is decreased.
until i add null byte to the end of the string.
-fsanitize=address gives error ==7126==ERROR: AddressSanitizer: heap-buffer-overflow on address.
if realloc free remaining block then why overflow occurs for the code below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUL '\0'
void check_allocation_success(char *ptr);
int main(void) {
char *str1, *str2;
str1 = malloc(sizeof(char)*17);
check_allocation_success(str1);
strncpy(str1, "0123456789ABCDEF", 16);
str2 = realloc(str1, 8);
check_allocation_success(str2);
printf("%s", str2);
free(str2);
return 0;
}
void check_allocation_success(char *ptr) {
if (ptr == NULL) {
printf("%s : %d : allocation failed.\n", __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
}
I know my question is duplicate but i am still confused. Some says we can't be sure the allocation always may free remaining block and some say we don't need to worry about old content.
If we dont need to worry about old content why is it still printing all old contents in above code.
I am using c99.

Related

Using calloc function for a test programm

I am a beginner in coding and I tried to this this little code were my idea was to set the memory allocation for 20 letter from 26 and after that to increase my memory space with realloc and print those letters again. Unfortunately I can't even complete the first step so maybe could someone help me to fix that.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i;
char ALPHABET[] = { 'a','b','c','d','e','f','g','h','i','j','k','l','n','o','p','q','r','s','t','u','v','w','x','y','z'};
char* alp = &ALPHABET;
alp = (char*)(calloc(20, sizeof(char)));
if (alp == NULL)
{
printf("Der Speicher konnte nicht reserviert werden! \n"); // Couldn't allocate the memory
return NULL;
}
for (i=0; i<alp; i++);
{
printf("Das ist ein Alphabet: %c ",ALPHABET[i]);
}
return 0;
}
thank you so much

static pointer overflow in bss

I'm using w00w00 exercises on static pointer overflow in bss. I put the buffer and buffer pointer into static struct to force overflowing the pointer. Otherwise, it put the pointer before and buffer and no overflow happens.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define BUFSIZE 16
#define ADDRLEN 4 /* # of bytes in an address */
int main()
{
u_long diff;
struct buf {
char buf[BUFSIZE];
char *bufptr ;
} ;
static struct buf a;
a.bufptr = a.buf, diff = (u_long)a.buf - (u_long)&a.bufptr;
printf("bufptr (%p) = %p, buf = %p, diff = 0x%x (%d) bytes\n",
&a.bufptr,a.bufptr, a.buf, diff, diff);
memset(a.buf, 'A', (u_int)(diff + ADDRLEN));
printf("bufptr (%p) = %p, buf = %p, diff = 0x%x (%d) bytes\n",
&a.bufptr, a.bufptr, a.buf, diff, diff);
return 0;
}
I'm currently getting this error when I used AddressSanitizer
==27643==ERROR: AddressSanitizer: negative-size-param: (size=-12)
SUMMARY: AddressSanitizer: negative-size-param ??:0 __asan_memset
==27643==ABORTING
Is there a flag or way to force the overflow?
Edit:
I figured out the problem. Diff result was -16.
I mad it look like this
diff = (u_long)&a.bufptr - (u_long)a.buf
Now it work fine.
Try size which is larger than struct size but not large enough to be interpreted as negative:
memset(a.buf, 'A', 1024);
Also be sure to compile with -fno-common as explained in Asan FAQ.

basic pointer use: segmentation fault, core dumped [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
I've spent hours scouring the internet for help. I'm very much a beginner at pointer use, and I've already come up against a wall: I keep getting the error Segmentation fault (core dumped). I'm trying to make a simple version of strncpy() using pointers:
int main(int argc, char *argv[]) {
char *x = "hello"; /* string 1 */
char *y = "world"; /* string 2 */
int n = 3; /* number of characters to copy */
for (int i=0; i<=n; i++) {
if(i<n) {
*x++ = *y++; /* equivalent of x[i] = y[i] ? */
printf("%s\n", x); /* just so I can see if something goes wrong */
} else {
*x++ = '\0'; /* to mark the end of the string */
}
}
}
(Edit: I initialized x and y, but still got the same fault.)
While on the quest to figure out what part of this was wrong, I tried another simple pointer thing:
int main(int argc, char *argv[]) {
char *s;
char *t;
int n; /* just initilaizing everything I need */
printf("Enter the string: ");
scanf("%s", s); /* to scan in some phrase */
printf("%s", s); /* to echo it back to me */
}
And lo and behold, I got another Segmentation fault (core dumped)! It let me scan in "hello", but replied with the fault. This code is so simple. What's wrong with my pointer use here?
In your second example, you don't actually allocate any memory. char *s only allocates a pointer to a char. You need to allocate memory somehow:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char s[100];
printf("Enter the string: ");
scanf("%s", s); /* to scan in some phrase */
printf("%s", s); /* to echo it back to me */
}
char s[100] declares memory on the stack, which will be deallocated automatically. If you'd like to allocate on the heap, use malloc / free:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char *s = malloc(100 * sizeof(char));
printf("Enter the string: ");
scanf("%s", s); /* to scan in some phrase */
printf("%s", s); /* to echo it back to me */
free(s);
}
Of course these simple examples assume your string will never be longer than 100 characters.
Your first example fails too, for a different reason.
char *x = "hello";
char *y = "world";
Those statements allocate strings in read-only memory, and thus you cannot modify it.
When you are using pointer to string, always rember that you cant modify it. It means you cant change the string characters. In Pointer to string, string always goes to read only memory.It mean memory can only be read not to modify.
This statement is causing segment fault;-
*x++ = *y++;
you cant do this also;-
int *p="cool";
*p="a"; //dereferencing
printf("%s",p); //segment fault

why fgets() not working here?

In the below code scanf() is working for getting the name from the user but fgets() is not working pls someone help me to understand why it's not working
#include <stdio.h>
#include <stdlib.h>
typedef struct university{
int roll_no;
char name[16];
}uni;
int main()
{
uni *ptr[5],soome;char i,j=0;
for(i=0;i<5;i++)
{
ptr[i]=(uni*)calloc(1,20);
if(ptr[i]==NULL)
{
printf("memory allocation failure");
}
printf("enter the roll no and name \n");
printf("ur going to enter at the address%u \n",ptr[i]);
scanf("%d",&ptr[i]->roll_no);
//scanf("%s",&ptr[i]->name);
fgets(&ptr[i]->name,16,stdin);
}
while(*(ptr+j))
{
printf("%d %s\n",ptr[j]->roll_no,ptr[j]->name);
j++;
}
return 0;
}
First of all, fgets(char *s, int n, FILE *stream) takes three argument: a pointer s to the beginning of a character array, a count n, and an input stream.
In the original application you used the address operator & to get the pointer not to the first element of the name[16] array, but to something else (to use the address operator, you should have referenced the first char in the array: name[0]).
You use a lot of magic numbers in your application (e.g. 20 as the size of the uni struct). In my sample I'm using sizeof as much as possible.
Given that you use calloc, I've used the fact that the first parameter is the number of elements of size equal to the second parameter to preallocate all the five uni struct at once.
Final result is:
#include <stdio.h>
#include <stdlib.h>
#define NUM_ITEMS (5)
#define NAME_LENGTH (16)
typedef struct university{
int roll_no;
char name[NAME_LENGTH];
} uni;
int main()
{
uni *ptr;
int i;
ptr = (uni*)calloc(NUM_ITEMS, sizeof(uni));
if(NULL == ptr) {
printf("memory allocation failure");
return -1;
}
for(i=0; i<NUM_ITEMS; i++) {
printf("enter the roll no and name \n");
printf("You're going to enter at the address: 0x%X \n",(unsigned int)&ptr[i]);
scanf("%d",&ptr[i].roll_no);
fgets(ptr[i].name, NAME_LENGTH, stdin);
}
for(i=0; i<NUM_ITEMS; i++) {
printf("%d - %s",ptr[i].roll_no,ptr[i].name);
}
free(ptr);
return 0;
}
Note: I've added a call to free(ptr); to free the memory allocated by calloc at the end of the application and a different return code if it's not possible to allocate the memory.

UNIX FIFO: How to allow only one writer/reader pair to use a FIFO?

I've written two programs: the first, the "writer", creates a FIFO and writes data into it. The second one, the "reader" runs in background and looks for data in the FIFO. Once data is there, the reader reads it out.
If I start e.g. two writers and two readers, they all can write/read into/from the same FIFO. How can I restrict it for 3rd and 4th readers/writers to use the FIFO and allow only one writer and one reader to use the FIFO?
My code:
FIFO Writer:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define BUFFERSIZE 50
#define CHMOD 0777
int main(int argc, char **argv)
{
char outbuf[BUFFERSIZE]; // outbuffer
int fifo, j, anzahl;
// fifo - pipe file deskriptor, j - counter, anzahl - Parameter.
if(argc!=2) // Check if parameter is ok
{
printf("Ungültiger Parameter! Bsp.: ./fifow 10\n");
return 1;
}
anzahl=atoi(argv[1]); // convert paramter to integer
mkfifo("namedpipe4", CHMOD); // make FIFO "namedpipe4"
fifo = open("namedpipe4",O_WRONLY); // open FIFO
//
for(j=0;j<anzahl;j++)
{
printf("Writer PID: %d writes record nr. %6d\n", getpid(), j+1);
sprintf(outbuf, "Writer PID: %d writes record nr. %6d\n", getpid(), j+1);
write(fifo, outbuf, BUFFERSIZE);
remove("namedpipe4"); // removing the fifo
sleep(1); // Wait 1 sec
}
close(fifo); //
exit(0);
}
FIFO Reader:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define BUFFERSIZE 50
int main(void)
{
char inbuf[BUFFERSIZE]; // inbuffer
int fifo, var;
printf("\n Waiting for a Pipe....\n");
while((fifo = open("namedpipe4",O_RDONLY)) == -1) // while "there is no such pipe"
{
remove("namedpipe4");
sleep(1);
}
while((var = read(fifo, inbuf, BUFFERSIZE)) > 0) // while "i can read"
{
printf("Reader PID: %d reads record: %s\n", getpid(), inbuf);
sleep(1);
}
close(fifo); //
printf("\n EOF..\n");
exit(0);
}
Given the code you posted in a separate answer, here is a modified version that fixes the problems you were having. See the comments for details, but in a nutshell:
The writer checks the return value of mkfifo is checked to see if another writer already created the pipe.
The reader gets an exclusive advisory lock on the pipe (via flock) after opening it, to avoid the race condition where a second reader could have opened the pipe before the first reader deleted it.
Writer:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h> /* needed for mkfifo */
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define BUFFERSIZE 50
#define CHMOD 0777
int
main (int argc, char **argv)
{
char outbuf[BUFFERSIZE];
int fifo, j, anzahl;
if (argc != 2)
{
printf("Ungültiger Parameter! Bsp.: ./fifow 10\n");
return 1;
}
anzahl=atoi(argv[1]);
/* mkfifo fails if the file already exists, which means there's a
* writer waiting for a reader. This assures that only one writer
* will write to the pipe, since it only opens the pipe if it was
* the one who created it.
*/
if (mkfifo("namedpipe4", CHMOD) == -1)
{
printf("namedpipe4 already exists\n");
return 1;
}
fifo = open("namedpipe4", O_WRONLY);
for (j = 0; j < anzahl; j++)
{
printf("Writer PID: %d writes record nr. %6d\n", getpid(), j + 1);
sprintf(outbuf, "Writer PID: %d writes record nr. %6d\n", getpid(), j + 1);
write(fifo, outbuf, BUFFERSIZE);
remove("namedpipe4");
sleep(1);
}
close(fifo);
exit(0);
}
Reader:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h> /* for flock */
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define BUFFERSIZE 50
int
main (int argc, char **argv)
{
char inbuf[BUFFERSIZE];
int fifo, var;
printf("\n Waiting for a Pipe....\n");
/* There are *two* ways the open can fail: the pipe doesn't exist
* yet, *or* it succeeded, but a different writer already opened
* it but didn't yet remove it.
*/
while (1)
{
while ((fifo = open("namedpipe4", O_RDONLY)) == -1)
{
/* Since you didn't specify O_CREAT in the call to open, there
* is no way that namedpipe4 would have been created by the
* reader. If there *is* now a namedpipe4, a remove here
* would delete the one the writer created!
*/
sleep(1);
}
/* Get an exclusive lock on the file, failing if we can't get
* it immediately. Only one reader will succeed.
*/
if (flock (fifo, LOCK_EX | LOCK_NB) == 0)
break;
/* We lost the race to another reader. Give up and wait for
* the next writer.
*/
close (fifo);
}
/* We are definitely the only reader.
*/
/* *Here* we delete the pipe, now that we've locked it and thus
* know that we "own" the pipe. If we delete before locking,
* there's a race where after we opened the pipe, a different
* reader also opened, deleted, and locked the file, and a new
* writer created a new pipe; in that case, we'd be deleting the
* wrong pipe.
*/
remove("namedpipe4");
while ((var = read(fifo, inbuf, BUFFERSIZE)) > 0)
{
printf("Reader PID: %d reads record: %s\n", getpid(), inbuf);
/* No need to sleep; we'll consume input as it becomes
* available.
*/
}
close(fifo);
printf("\n EOF..\n");
exit(0);
}
Create the FIFO using pipe(2), and only give the file descriptors for each end of the FIFO to the appropriate process when they get forked from the parent process. (Alternatively, have the reader call pipe(2) and fork the writer, or vice versa.) Since the FIFO never lives on the filesystem, it's impossible for any other process to access it.
If you must use a named FIFO, delete the FIFO after the reader and writer have opened it. The underlying FIFO will still exist as long as the reader and writer have it open, but no new processes will be able to open it. However, there will be a race condition where a second reader or writer could open the FIFO before you've deleted it.

Resources