How can I fix this simple C overflow? [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm very new to this. I am trying to re-write this code in order to remove the buffer overflow that is picked up in lines 12 + 19.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE (1024)
int main(int argc, char* argv[]) {
char* inBuf;
char* outBuf;
char* fmt = "the winner is: %s";
inBuf = (char*) malloc(BUF_SIZE);
if (inBuf == NULL) {
return -1;
}
read(0, inBuf, BUF_SIZE);
outBuf = (char*) malloc(BUF_SIZE);
if (outBuf == NULL) {
return -1;
}
sprintf(outBuf, fmt, inBuf);
fprintf(stdout, "%s\n", outBuf);
fprintf(stderr, "%s\n", outBuf);
free(inBuf);
free(outBuf);
}
If someone could provide some insight on the best way to approach this? would be much appreciated thank you.

Because you use the read function to read user input, you're reading raw bytes as opposed to a string. So what it read in doesn't include a null terminating byte, so you don't have a null terminated string since the buffer returned by malloc is uninitialized.
Use calloc instead of malloc, which returns a buffer initialized to all zeros.
inBuf = calloc(BUF_SIZE + 1, 1);
Note that this leaves an extra byte for a terminating null character.
You should also be checking the return value of read for an error, and you shoudn't cast the return value of malloc/calloc/realloc.
Your output buffer size is also too small. It should be at least the size of the input string plus the format string.
outBuf = (char*) malloc(BUF_SIZE + 1 + strlen(fmt));

Related

Why do we need to subtract 1 from the size of the buffer to get the size of the column? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 10 months ago.
Improve this question
I'm making a program that takes a file of an unknown size as an input and dynamic allocate it as much as the size of the array. Why do we need to subtract 1 from the size of the buffer to get the size of the column?
This is part of the code.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 500
void CountRowCol(FILE* fp);
void allocateMemory();
int main()
{
FILE* fp = NULL;
fp = fopen("test.txt", "r");
if (fp != NULL)
{
CountRowCol(fp);
allocateMemory();
}
else
printf("There is No file\n");
fclose(fp);
return 0;
}
void CountRowCol(FILE* fp)
{
int row = 0; int col = 0;
char buffer[MAX_SIZE];
if (fgets(buffer, 1000, fp))
{
col = strlen(buffer) - 1;
row = 1;
}
while (fgets(buffer, 1000, fp))
{
row++;
}
fclose(fp);
fp = NULL;
}
Why do we need to subtract 1 from the size of the buffer to get the size of the column?
As code does not use col, col = strlen(buffer) - 1; has no direct usefulness. #shjeff
Let us assume code is trying to find the length of the first line and not count a final '\n' #David Ranieri
.
strlen(buffer) - 1, code risks 2 mistakes:
A '\n' may not exist in buffer[], so finding its offset is moot. E.g. the line of input may exceed buffer space, so no '\n' saved.
Although rare to first read a null character, it is possible, then strlen(buffer) is an unsigned 0 and strlen(buffer) - 1 is a very large value: SIZE_MAX. Assigning that to an int leads to implementation defined behavior, possible returning INT_MAX.
A better way to lop off a potential '\n':
buffer[strcspn(buffer, "\n")] = 0;
col = strlen(buffer);
Wrong size
User code is lying to fgets() as buffer is less than 1000 bytes. #the busybee
#define MAX_SIZE 500
...
// if (fgets(buffer, 1000, fp))
if (fgets(buffer, sizeof buffer, fp))
fgets(buffer, 1000, fp
This reads a line (assuming it fits in 999 bytes, one byte is used for string terminator, '\0').
This line includes the newline character, '\n'.
Subtracting 1 excludes that.
You might additionally want to remove the line feed from the string:
size_t len = strlen(buffer);
if (len > 0 && buffer[len-1] == '\n') {
// reduce line length by 1 and overwrite newline with 0
buffer[--len] = '\0';
} else {
// handle line which does not end in newline
}
Missing newline might be because file ended and did not have newline at the end, or because line was longer than the buffer. Here you can probably just... print error message and exit, if you aren't required to handle such input.
In the C standard library, the character reading functions such as getchar return a value equal to the symbolic value (macro) EOF to indicate that an end-of-file condition has occurred. The actual value of EOF is implementation-dependent and must be negative (but is commonly −1, such as in glibc). Block-reading functions return the number of bytes read, and if this is fewer than asked for, then the end of file was reached or an error occurred (checking of errno or dedicated function, such as ferror is often required to determine which).
Source

Semantically identical codes give different results [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I couldn't wrap my head around this one, hope the title isn't too misleading. Why does write behave differently when it comes to it's third argument count in the two snippets of code? It would seem that calling a function instead of specifying a number in write is a bad thing, but it doesn't seem like a big deal.
Wrong version:
int main(int argc, char const *argv[])
{
char format[50];
char formattedTime[50];
time_t t;
if (read(STDIN_FILENO, format, 50) < 0)
fatalError("read() error");
time(&t);
strftime(formattedTime, 50, format, localtime(&t));
if (write(STDOUT_FILENO, formattedTime, strlen(formattedTime) + 1) != strlen(formattedTime) + 1)
fatalError("write() error");
return 0;
}
Right version:
int main(int argc, char const *argv[])
{
char format[50]; //zeljeni format
char formattedTime[50]; //formatirano vreme
time_t t; // trenutno vreme
// citamo s ulaza zeljeni format vremena
if (read(STDIN_FILENO, format, 50) < 0)
fatalError("read() error");
// zapisujemo trenutno vreme
time(&t);
strftime(formattedTime, 50, format, localtime(&t));
int n;
n = strlen(formattedTime) + 1;
// ispisujemo na izlaz
if (write(STDOUT_FILENO, formattedTime, n) != n)
fatalError("write() error");
return 0;
}
Right output:
%a %b %d
Wed Jan 16
Wrong output:
%a %b %d
Wed Jan 16
0
Why would calcuating n just a step before the call to write make all the difference?
EDIT:
Hope this satisfies all the info. The gibberish is different every time, but the point remains.
If you really have that behavior this probably means the null character is missing in formattedTime and by chance n is just after in the stack and introduces a null char by its presence, or an equivalent because of the data saved in the stack
The read function is primarily intended to read binary data, not strings. As such, it reads only the characters you enter (i.e. a sequence of characters followed by a newline) without adding a null terminating byte. As a result, you don't have a properly formatted string, so using strftime can read past what was written into bytes that were not initialized and possibly past the end of the array. This invokes undefined behavior.
The "right version" seems to work because you got "lucky". That's one of the ways undefined behavior can manifest itself. Other people could see the opposite results of what you see.
You need to capture how many bytes were read and manually add a terminating null byte to the array:
int rval;
if ((rval=read(STDIN_FILENO, format, 49)) < 0)
fatalError("read() error");
format[rval] = 0;

C- leading zero without printf [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Ethernet starter kit(PIC32MX9795F512L)
language: C
MPLAB IDE 8.92
Compiler: XC32 v1.3
Hello i want to add leading zeros to my variables. At the end i want to use the in an array.
For example: c=10*a+b. When c=5 it should be 05. I cant use any printf function or am I wrong?
You can use printf() to simply print a formatted number to standard output:
int c = 5;
fprintf(stdout, "c [%02d]\n", c);
If you can't use printf(), another option is to store the padded value in a char * or string. You can instead use sprintf() to write the formatted string to a char * buffer.
For example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[]) {
{
char* c_str = NULL;
int c_int = 5;
int c_str_length = 3; /* two bytes for "0", "5", and one byte for the nul terminator */
c_str = malloc(c_str_length);
if (!c_str) {
fprintf(stderr, "Error: Could not allocate space for string!\n");
return EXIT_FAILURE;
}
int n = sprintf(c_str, "%02d", c_int);
if (n != c_str_length) {
fprintf(stderr, "Error: Something went wrong in writing the formatted string!\n");
free(c_str);
return EXIT_FAILURE;
}
fprintf(stdout, "c_str: [%s]\n", c_str);
free(c_str);
return EXIT_SUCCESS;
}
If you go this route, you can see how you could do some error checking along the way. You'll need to think about string length (hint: log10()), or use a static char [] array in place of a char * of sufficiently long length.
It is quite easy to add a leading zero, provided you take care of negative values too. You said you want to write to an array, so I used sprintf but if you want to output directly, you can use printf in a similar way.
char cstr[24];
int c = 10 * a + b;
if (c > 0) {
sprintf(cstr, "0%d", c);
} else if (c < 0) {
sprintf(cstr, "-0%d", -c);
} else {
//sprintf(cstr, "00");
sprintf(cstr, "0"); // depending on your needs
}

Is there a good alternative to fgets? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I'm just a young computer science student, and currently I'm a bit confused about what is the best practice to read a string from stdin. I know that there are a lot of ways to do that, some safer than other, and so on...
I'm currently in need of a function that prevents buffer overflow and appends a null terminator character (\0) to the end of the string. I found fgets really useful for that, but ... It stops reading with \n or EOF! What if I want the user to input more than one line at time? Are there some other function that can help me doing that?
I'm sorry if this question can seem silly to some of you, but please, understand me!
Any help would be appreciated.
#define INITALLOC 16 /* #chars initally alloced */
#define STEP 8 /* #chars to realloc by */
#define END (-1) /* returned by getline to indicate EOF */
#define ALLOCFAIL 0 /* returned by getline to indicate allocation failure */
int getline(char **dynline)
{
int i, c;
size_t nalloced; /* #chars currently alloced */
if ((*dynline = malloc(INITALLOC)) == NULL)
return ALLOCFAIL;
nalloced = INITALLOC;
for (i = 0; (c = getchar()) != EOF; ++i) {
/* buffer is full, request more memory */
if (i == nalloced)
if ((*dynline = realloc(*dynline, nalloced += STEP)) == NULL)
return ALLOCFAIL;
/* store the newly read character */
(*dynline)[i] = c;
}
/* zero terminate the string */
(*dynline)[i] = '\0';
if (c == EOF)
return END;
return i+1; /* on success, return #chars read successfully
(i is an index, so add 1 to make it a count */
}
This function allocates memory dynamically, so the caller needs to free the memory.
This code is not perfect. If, on reallocation, there is a failure, NULL overwrites the previous, perfectly-good data causing a memory leak and loss of data.
If a newline is encountered and fgets returns, you can run it again as many times as necessary to read as many lines as you want. A loop is useful for this.
If EOF is encountered, you have reached the end of the file(/stream) and there is no point in running it again, because there is nothing left to read.
An example showing the logic to read an entire string to EOF from stdin follows.
There are many ways to do this, and this is just one, but it shows the general logic.
The result buffer grows as the input is read, and there are no bounds on this – so if EOF is never reached you will eventually run out of memory and the program will exit. A simple check could avoid this, or depending on your application you could process the data as it comes in and not need to store it all.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LINE_BUFFER_SIZE 256
// Each time this is exhausted, the buffer will be increased in size by this amount again.
#define INITIAL_BUFFER_SIZE 2048
int main (int argc, char **argv) {
char *result = malloc(INITIAL_BUFFER_SIZE);
if (!result) {
// Out of memory.
return 1;
}
size_t totalBytesRead = 0;
size_t bytesAllocated = INITIAL_BUFFER_SIZE;
char buf[LINE_BUFFER_SIZE];
while (fgets(buf, LINE_BUFFER_SIZE, stdin)) {
size_t bytesRead = strlen(buf);
size_t bytesNeeded = totalBytesRead + bytesRead + 1;
if (bytesAllocated < bytesNeeded) {
char *newPtr = realloc(result, bytesAllocated + INITIAL_BUFFER_SIZE);
if (newPtr) {
result = newPtr;
bytesAllocated += INITIAL_BUFFER_SIZE;
}
else {
// Out of memory.
free(result);
return 1;
}
}
memcpy(result + totalBytesRead, buf, bytesRead);
totalBytesRead += bytesRead;
}
result[totalBytesRead] = '\0';
// result contains the entire contents from stdin until EOF.
printf("%s", result);
free(result);
return 0;
}
On POSIX systems, you have getline. It is able to read an arbitrarily wide line (till exhausting resources) in heap allocated memory.
You can also repeatedly call fgetc ... (BTW, you should define exactly what is a string for you)
On Linux, you can read an editable line from the terminal (that is, stdin when it is a tty) using GNU readline.
To read some kind of strings, you might use fscanf with e.g. %50s or %[A-Z] etc...
And you can read an array (of bytes, or some other binary data) using fread
You might read an entire line and parse it later (perhaps using sscanf). You could read several lines and build some strings in heap memory (e.g. using asprintf or strdup on systems having it) from them.

Program to read input lines of any length in C [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
And I want it to print to output as is. Curently I am using this code
#include <stdio.h>
#include <ctype.h>
#define BUFFER_SIZE 2000
int main(void)
{
char buffer[BUFFER_SIZE];
while(fgets (buffer, BUFFER_SIZE, stdin) !=NULL)
{
printf("%s",buffer);
}
return 0;
}
Then I want the program to be able to skip html tags in the original text but I don't know exactly how to work around that.
You should use getline(3) (at least on Posix compliant systems). Your fgets based code won't work with very long lines (because a very long line would be "truncated": all of it would be read, but only BUFFER_SIZE characters would have been copied, and the rest of the line ignored).
You could code
char* linebuf=NULL;
size_t linesize=0;
while (!feof(stdin)) {
ssize_t linelen = getline(&linebuf, &linesize, stdin);
if (linelen<0) { perror("getline"); exit(EXIT_FAILURE); };
fputs(linebuf, stdout);
}
In the above code, the linebuf will (unless failure) be grown to the widest line size. You should free(linebuf) after that loop...

Resources