Why is ftell() telling me that the parameter is invalid? - c

In the debugger, I get an unhandled exception from (ucrtbased.dll) in Executable.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
I believe I am following the parameters of the functions as documented, so I am quite confused as to why this is happening.
The code is from me trying to encrypt a text file by using XOR, if this helps to provide any clarity. Thank you for reading this!
#include <stdio.h>
#include <string.h>
#include <windows.h>
int WINAPI WinMain()
{
FILE* ptr;
ptr = fopen("C:\\Users\\User\\Desktop\\text.txt", "rb+");
fseek(ptr, 0, SEEK_END);
long endpoint = ftell(ptr); //<<<<<<<<<<<<<<<<<<<<<< Area where Unhandled exception occurs
char* buffer = malloc(endpoint + 1);
endpoint = fread(buffer, 1, endpoint, ptr);
rewind(ptr);
char* temp = buffer;
for (int i = 0; i < endpoint; i++, temp++)
{
*temp = *temp ^ 21;
}
fwrite(temp, 1, endpoint, ptr);
free(buffer);
fclose(ptr);
return 0;
}

Related

Passing buffer to function for writing

I'm trying to implement a quick prototype program to prepare a message that I intend to use as a tcp socket communication protocol.
I'm new at this, and I can't quite understand why running the following prints (null). Am I failing at passing the pointer to the subroutine?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *header = "testhd";
void pack_message(char *body, char *buffer)
{
size_t body_size, msg_size, buffer_size;
char hex_size[11];
body_size = strlen(body);
snprintf(hex_size, 11, "0x%x", body_size);
msg_size = 16 + body_size;
buffer_size = msg_size + 1;
if (!buffer){
buffer = malloc(buffer_size);
}else{
buffer = realloc(buffer, buffer_size);
}
memset(buffer, 0, buffer_size);
strcat(buffer, header);
strcat(buffer, hex_size);
strcat(buffer, body);
}
int main(){
char *buffer = NULL;
char *body = "testmsg";
pack_message(body, buffer);
printf("%s", buffer);
return 0;
}
Please note that char *buffer in main function and char *buffer in pack_message function are two different pointers which are pointing to the same NULL address.
So in Your case functiom pack_message is working with local pointer and that's the reason why running Your code prints null.
To make Your code work You could potentially take an approach where You pass an address of pointer itself as an argument to the pack_message function so main function could look like that:
int main(){
char *buffer = NULL;
char *body = "testmsg";
pack_message(body, &buffer);
printf("%s", buffer);
return 0;
}
Your pack_message function should be changed to:
void pack_message(char *body, char **buffer)
{
size_t body_size, msg_size, buffer_size;
char hex_size[11];
body_size = strlen(body);
snprintf(hex_size, 11, "0x%zx", body_size);
msg_size = 16 + body_size;
buffer_size = msg_size + 1;
if (NULL == *buffer){
*buffer = malloc(buffer_size);
}else{
*buffer = realloc(*buffer, buffer_size);
}
memset(*buffer, 0, buffer_size);
strcat(*buffer, header);
strcat(*buffer, hex_size);
strcat(*buffer, body);
}
Please note that there I changed also one more potential issue:
snprintf(hex_size, 11, "0x%zx", body_size);
As body_size is of type size_t it is better idea to use %zx as size_t can be different size than unsigned integer, for details on printf please take a look at: https://cplusplus.com/reference/cstdio/printf/
Similar approach can be taken to char *body = "testmsg"; especially when its value will be much longer string.
For further improvements I would recommend to redesign pack_message function to return a pointer to allocated buffer as it will lower the chances to forget about freeing memory when not needed anymore.

Given a time in -hour AM/PM format, convert it to military (24-hour) time

I am trying to solve this task on hackerrank but having problem when submitting solution. Here is my solution and the error got, I would like someone to point out my mistakes and if possible give a better solution to this question.(timeConversion() is the only code the user have to complete all the other functions are inbuilt)
#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* readline();
char* timeConversion(char* s)
{
int hr;
char h[2],mr, hrs[2],m[6];
mr=s[8];
for(int i=0; i<2; i++)
{h[i]=s[i];}
for(int i=0; i<5; i++)
{m[i]=s[i+3];}
hr= atoi(h);
if((mr=="A")&&(hr==12))
{strcpy(hrs, "00");}
if((mr=='P')&&(hr!=12))
{
hr=hr+12;
itoa(hr,hrs,10);
}
return strcat(hrs,m);
}
int main()
{
FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");
char* s = readline();
char* result = timeConversion(s);
fprintf(fptr, "%s\n", result);
fclose(fptr);
return 0;
}
char* readline() {
size_t alloc_length = 1024;
size_t data_length = 0;
char* data = malloc(alloc_length);
while (true) {
char* cursor = data + data_length;
char* line = fgets(cursor, alloc_length - data_length, stdin);
if (!line) { break; }
data_length += strlen(cursor);
if (data_length < alloc_length - 1 || data[data_length - 1] == '\n') { break; }
size_t new_length = alloc_length << 1;
data = realloc(data, new_length);
if (!data) { break; }
alloc_length = new_length;
}
if (data[data_length - 1] == '\n') {
data[data_length - 1] = '\0';
}
data = realloc(data, data_length);
return data;
}
This is the error I got
Solution.c: In function ‘timeConversion’:
Solution.c:38:11: warning: comparison between pointer and integer
if((mr=="A")&&(hr==12))
^~
Solution.c:38:11: warning: comparison with string literal results in unspecified behavior [-Waddress]
Solution.c:44:13: warning: implicit declaration of function ‘itoa’; did you mean ‘atol’? [-Wimplicit-function-declaration]
itoa(hr,hrs,10);
^~~~
atol
In file included from /usr/include/string.h:494,
from Solution.c:7:
In function ‘strcpy’,
inlined from ‘timeConversion’ at Solution.c:39:10:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:90:10: warning: ‘__builtin___memcpy_chk’ forming offset 3 is out of the bounds [0, 2] of object ‘hrs’ with type ‘char[2]’ [-Warray-bounds]
return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Solution.c: In function ‘timeConversion’:
Solution.c:29:19: note: ‘hrs’ declared here
char h[2],mr, hrs[2],m[6];
^~~
/usr/bin/ld: ./cct5tsGb.o: in function `timeConversion':
/tmp/submission/20200802/11/40/hackerrank-a082dac4956371ebbffb5bdc5098ce57/code/Solution.c:44: undefined reference to `itoa'
collect2: error: ld returned 1 exit status
Without looking to what the code does, I can point:
Solution.c:38:11: warning: comparison between pointer and integer
if((mr=="A")&&(hr==12))
^~
You are comparing a char to a char*. You should compare like below.
if((mr=='A')&&(hr==12))
The other issue is here:
{strcpy(hrs, "00");}
The hrs variable has only 2 bytes size, but you are trying to write 3 bytes: 0, 0 and null terminator. You need to change the variable size to 3.
Regarding the ´itoa´ warning, please see this: Where is the itoa function in Linux?

String returned from C function is garbage

i've been working on a RPG in C language lately, and i've come accross some difficulties for saving / loading some datas from a text file.
Here is the (simplified to make it short) code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct player{
int id;
char* name;
};
void save(struct player* player)
{
FILE* fp = 0;
char* buffer = 0;
fp = fopen("./gamesave.txt", "w");
fclose(fp);
buffer = malloc(80);
memset(buffer, 0, 80);
snprintf( buffer, 80, "%d|%s|\n", player->id, player->name);
fp = fopen("./gamesave.txt", "a");
fputs(buffer, fp);
free(buffer);
fclose(fp);
}
struct player* load()
{
FILE* fp = 0;
char* buffer = 0;
struct player* player = malloc(sizeof(struct player));
char tokens[] = "|\n";
buffer = malloc (80);
memset(buffer, 0, 80);
fp = fopen("./gamesave.txt", "r");
if (fgets(buffer, 80, fp)) {
char temp[20];
player->id = atoi(strtok(buffer, tokens));
strcpy(temp, strtok(NULL, tokens));
player->name = temp;
printf("during load : name is %s\n", player->name);
}
fclose(fp);
free(buffer);
return player;
}
void main()
{
struct player* player = malloc(sizeof(struct player));
player->id = 5;
player->name = "Bobby";
printf("before save : my name is %s and id is %d\n", player->name, player->id);
save(player);
struct player* playerN = load();
printf("after load : name is %s and id is %d", playerN->name, playerN->id);
}
This is my latest try in doing this but i've tried many differents ways of doing it, but it almost always ends in the same problem : i can't seem to get the right values for strings although it works for integers.I can print the name of the player before save, during the load function, but after the load it just prints garbage (the id works just fine).
My guess is that it has to do with some kind of memory problem but that's it, couldn't solve it after hours and hours.
Thanks in advance.
You need to allocate space for player->name.
You are using automatic variable temp for this, and its lifetime ends when the function returns. Auto variables are on the stack.
So you are taking an address on the stack and keeping it as your object. This leaks a pointer to your current stack level because you return it. It's OK to use pointers to automatic variables, but only while that function instance is active, i.e., in it's life cycle and in functions it calls.

C: System calls and pointers to reverse a file

Solved. Thanks lutogniew.....just over complicating it...
So I am having some trouble with a homework assignment. The assignment is to take in a file (using only system calls), reverse it and write an output file with that reversed data on it (ASCII only). A catch is that the reverse section has to be done with pointers. I did the following below, which does work. However, it does not use pointers to reverse.
My question I guess, is how can I access something like data[] using pointers? Or, how can I read from the file into it. Everything I tried (mostly char**) only reads in null.
Any help would be much appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int i = 0;
int fileOut = open("output.txt", O_WRONLY | O_APPEND);
int fileIn = open("input.txt", O_RDONLY);
int start = lseek(fileIn, 0 , SEEK_CUR);
int end = lseek(fileIn, 0 , SEEK_END);
int restart = lseek(fileIn, 0-end , SEEK_CUR);
char data[end];
char reverseData[end];
read(fileIn, data, end);
for(i = 0; i< end; i++){
reverseData[i] = data[end-(i+1)];
}
write(fileOut, reverseData, end);
return 0;
}
After Accept Answer.
Something for OP to consider as another approach:
For fun, a not-so-serious recursive approach to reverse the file.
void reverse(int fileIn, int fileOut) {
char data;
if (read(fileIn, &data, 1) == 1) {
reverse(fileIn, fileOut);
write(fileOut, &data, 1);
}
}
int main(void) {
int fileOut = open("output.txt", O_WRONLY | O_APPEND);
int fileIn = open("input.txt", O_RDONLY);
reverse(fileIn, fileOut);
close(fileIn);
close(fileOut);
return 0;
}
You must understand that what is presented to you as an array in C, in reality is just a pointer, pointing to the beginning of the memory belonging to that array. This snippet should make everything quite clear:
int test[] = { 1, 2, 3 };
int* ptr = test + 2; // ptr now points to the third element
EDIT
As for loading data into an array: again, remember that array itself is just a pool of memory (a buffer) - it begins where the pointer mentioned above points to, and has the size equal to numberOfElements * sizeOfSingleElement. Now look at the signature of the read function:
size_t read(int fildes, void* buf, size_t nbytes);
It reads nbytes into buffer pointed to by buf. Rings a bell?

Segmentation fault when returning a struct

I am trying to do a pretty simple thing - it is reading a file and then turning it into a char** splitting it into lines. However when I return a struct containing the char** and size i get Segmentation fault. I read here: C segmentation fault before/during return statement that it's probably "mangled stack". I still however don't know what I did to mangle it. This is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "comp_words.h"
#define BLOCK 4096
struct sized_str {
char* str;
long size;
};
struct sized_arr {
char** content;
int size;
};
struct sized_str readfile(char* name) {
FILE *f;
long filesize;
char *buf;
struct sized_str res;
int r, p = 0;
f = fopen(name, "r");
fseek(f, 0, SEEK_END);
filesize = ftell(f);
rewind(f);
buf = calloc(filesize + 1, sizeof(char));
while ((r = fread(buf + p, sizeof(char), BLOCK, f))) {
p += r;
}
res.str = buf;
res.size = filesize + 1;
return res;
}
struct sized_arr read_dict() {
struct sized_str file_content;
struct sized_arr result;
char *buf, *buf_cpy, *buf_cpy_point, *line, **res;
int i = 0, j, line_count = 0;
file_content = readfile("/var/tmp/twl06.txt");
buf = file_content.str;
buf_cpy = (char*)malloc(file_content.size * sizeof(char));
strcpy(buf_cpy, buf);
buf_cpy_point = buf_cpy;
while (strtok(buf_cpy_point, "\n\r")) {
line_count++;
buf_cpy_point = NULL;
}
res = (char**)malloc(sizeof(char*) * line_count);
while ((line = strtok(buf, "\n\r"))) {
res[i] = (char*)malloc(sizeof(char) * strlen(line));
j = 0;
while ((res[i][j] = tolower(line[j]))) {
j++;
}
buf = NULL;
}
free(buf_cpy);
result.size = line_count;
result.content = res;
return result;
}
// ...
int main (int argc, char** argv) {
struct sized_str input;
struct sized_arr dict;
dict = read_dict();
// ...
return 0;
The code segfaults while returning from read_dict function.
At least at first glance, this seems to have a couple of problems. First:
while ((line = strtok(buf, "\n\r"))) {
To use strtok you normally pass the buffer on the first all, then make subsequent calls passing "NULL" for the first parameter until strtok returns a NULL (indicating that it's reached the end of the buffer). [Edit: upon further examination, it's apparent this isn't really a bug -- as pointed out by #Casablanca, he sets buf to NULL in the loop so the second and subsequent iterations actually do pass NULL for the first parameter -- so the current code is a bit hard to understand and (at least arguably) somewhat fragile, but not actually wrong.]
Second, when you allocate your space, it looks like you're not allocating space for the terminating NUL:
res[i] = (char*)malloc(sizeof(char) * strlen(line));
At least at first glance, it looks like this should be:
res[i] = malloc(strlen(line)+1);
[As an aside, sizeof(char)==1 and casting the return from malloc can mask the bug of failing to #include <stdlib.h> to get a proper prototype in scope.]
Some of your other code isn't exactly wrong, but strikes me as less readable than ideal. For example:
j = 0;
while ((res[i][j] = tolower(line[j]))) {
j++;
}
This appears to be a rather obfuscated way of writing:
for (j=0; line[j] != '\0'; j++)
res[i][j] = tolower((unsigned char)line[j]);
Also note that when you call tolower, you generally need/want to cast the parameter to unsigned char (passing a negative value gives undefined behavior, and quite a few characters with accents, umlauts, etc., will normally show up as negative in the typical case that char is signed).
You also seem to have a memory leak -- read_dict calls readfile, which allocates a buffer (with calloc -- why not malloc?) and returns a pointer to that memory in a structure. read_dict receives the structure, but unless I've missed something, the struct goes out of scope without your ever freeing the memory it pointed to.
Rather than try to find and fix the problem you've seen, my immediate reaction would be to start over. It seems to me that you've made the problem considerably more complex than it really is. If I were doing it, I'd probably start with a function to allocate space and read a line into the space, something on this order:
// Warning: Untested code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *readline(FILE *file) {
char *buffer = NULL;
size_t current_size = 1;
char *temp;
const int block_size = 256;
do {
if (NULL == (temp = realloc(buffer, current_size+block_size)))
break;
buffer = temp;
buffer[current_size-1] = '\0';
if (fgets(buffer+current_size-1, block_size, file)==NULL)
return strlen(buffer) > 0 ? buffer : NULL;
current_size += block_size-1;
} while (strchr(buffer, '\n') == NULL);
strtok(buffer, "\n");
if (NULL != (temp = realloc(buffer, strlen(buffer)+1)))
buffer =temp;
return buffer;
}
Once that's working, reading all the lines in the file and converting them to upper-case comes out something like:
// Warning: more untested code.
while (res[i] = readline(file)) {
size_t j;
for (j=0; res[i][j]; j++)
res[i][j] = toupper((unsigned char)res[i][j]);
++i;
}
It looks like you forgot to increment i after storing each line into the result array, so you end up storing all lines into res[0]. But you still set result.size = line_count at the end, so all array elements beyond the first are undefined. An i++ at the end of this loop: while ((line = strtok(buf, "\n\r"))) should fix it.

Resources