I'm trying to open an exe file and place input taken from the user and replace existing data (overwriting it) of the same length at specific locations. I can do this with my code, but I'm seeing data corruption in other parts of my file. This is my first time with C++, I've tried looking at everything I could to help myself, but I'm at a loss. Only thing I can think is that its related to a null string char at the end of 'char test1[100];' (If I read the documentation right). But doesnt help my issue of resolving the issue. See linked image for example from Hex Viewer of Output and Original
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *key;
key=fopen ("Testfile.exe","r+b");
char test1[100];
char test2[100];
printf("Test data to input:");
fgets(test1, sizeof test1, stdin);
printf("Second test data to input:");
fgets(test2, sizeof test2, stdin);
fseek (key,24523,SEEK_SET); //file offset location to begin write
fwrite (test1,1,sizeof(test1),key);
fseek (key,24582,SEEK_SET); //file offset location to begin write
fwrite (test2,1,sizeof(test2),key);
fseek (key,24889,SEEK_SET); //file offset location to begin write
fwrite (test2,1,sizeof(test2),key);
fclose(key);
printf ("Finished");
return(0);
}
After my initial edits, I was still fighting with a Null Terminator being written at the end of my string (and thus affecting operation of the edited exe file). After a bit more reading this is my final solution that works as intended without any weird data being written. I used scanf ("%10s") to ensure only my string was being used and to get rid of any Null Terminator. Does anyone see anything majorly wrong here or improvements to be made? Eventually I'd like to implement string length checking to ensure proper length was input by user. Thanks for everyone's help.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *key;
key=fopen ("test.exe","r+b");
char test1[10];
char test2[32];
printf("Input Test1 data:");
scanf ("%10s",test1); //only read 10 Chars
printf("Input test2 data:");
scanf ("%32s",test2); //only read 32 Chars
fseek (key,24523,SEEK_SET); //file offset location to begin write
fputs (test1,key);
fseek (key,24582,SEEK_SET); //file offset location to begin write
fputs (test2,key);
fseek (key,24889,SEEK_SET); //file offset location to begin write
fputs (test2,key);
fclose(key);
printf ("Finished");
return(0);
}
It looks like you're to write a string into the exe file but actually you're writing a string padded with garbage values up to a length of 100 bytes.
If you just want to write the string, replace fwrite with fputs.
sizeof(array) gives the allocated size of the static array (100 in this case) , not the string length. string length is done via strlen() which doesn't include the terminating NULL character.
You have two problems.
First: you're writing 100 byte buffers which have not been initialized except via fgets()... everything not put in there by fgets() is whatever happened to be in memory (on the stack in this case).
Second: you're writing 100 bytes with each write however your seek does not advance to at least 100 bytes later, meaning the second write() in this snippet partially overwrites the first.
Related
RESOLVED
I'm trying to make a simple file loader.
I aim to get the text from a shader file (plain text file) into a char* that I will compile later.
I've tried this function:
char* load_shader(char* pURL)
{
FILE *shaderFile;
char* pShader;
// File opening
fopen_s( &shaderFile, pURL, "r" );
if ( shaderFile == NULL )
return "FILE_ER";
// File size
fseek (shaderFile , 0 , SEEK_END);
int lSize = ftell (shaderFile);
rewind (shaderFile);
// Allocating size to store the content
pShader = (char*) malloc (sizeof(char) * lSize);
if (pShader == NULL)
{
fputs ("Memory error", stderr);
return "MEM_ER";
}
// copy the file into the buffer:
int result = fread (pShader, sizeof(char), lSize, shaderFile);
if (result != lSize)
{
// size of file 106/113
cout << "size of file " << result << "/" << lSize << endl;
fputs ("Reading error", stderr);
return "READ_ER";
}
// Terminate
fclose (shaderFile);
return 0;
}
But as you can see in the code I have a strange size difference at the end of the process which makes my function crash.
I must say I'm quite a beginner in C so I might have missed some subtilities regarding the memory allocation, types, pointers...
How can I solve this size issue?
*EDIT 1:
First, I shouldn't return 0 at the end but pShader; that seemed to be what crashed the program.
Then, I change the type of reult to size_t, and added a end character to pShader, adding pShdaer[result] = '/0'; after its declaration so I can display it correctly.
Finally, as #JamesKanze suggested, I turned fopen_s into fopen as the previous was not usefull in my case.
First, for this sort of raw access, you're probably better off
using the system level functions: CreateFile or open,
ReadFile or read and CloseHandle or close, with
GetFileSize or stat to get the size. Using FILE* or
std::filebuf will only introduce an additional level of
buffering and processing, for no gain in your case.
As to what you are seeing: there is no guarantee that an ftell
will return anything exploitable as a numeric value; it could
very well be just a magic cookie. On most current systems, it
is a byte offset into the physical file, but on any non-Unix
system, the offset into the physical file will not map directly
to the logical file you are reading unless you open the file in
binary mode. If you use "rb" to open the file, you'll
probably see the same values. (Theoretically, you could get
extra 0's at the end of the file, but practically, the OS's
where that happened are either extinct, or only used on legacy
mainframes.)
EDIT:
Since the answer stating this has been deleted: you should loop
on the fread until it returns 0 (setting errno to 0 before
each call, and checking it after the return to see whether the
function returned because of an error or because it reached the
end of file). Having said this: if you're on one of the usual
Windows or Unix systems, and the file is local to the machine,
and not too big, fread will read it all in one go. The
difference in size you are seeing (given the numerical values
you posted) is almost certainly due to the fact that the two
byte Windows line endings are being mapped to a single '\n'
character. To avoid this, you must open in binary mode;
alternatively, if you really are dealing with text (and want
this mapping), you can just ignore the extra bytes in your
buffer, setting the '\0' terminator after the last byte
actually read.
I am looking to have an Atmel 1284P microcontroller parse through a MIDI file stored on an SD card and activate solenoids to play music. I am experimenting by attempting to save an entire MIDI file to a buffer. As I understand it, the entire MIDI file is ultimately a series of command/data and other bytes. As such, I thought that I would be able to read the file using the c++ "fopen" method with a 'read byte' parameter. However, it is only returning the first four bytes of the file (the MTHD portion of the header). I could utilize a C++ MIDI library but I am honestly curious about this. This is the output:
MThd
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE* midiFile;
midiFile = fopen("C:/Users/Preston/Desktop/cantina.mid","rb");
char* buffer;
long lsize;
size_t result;
fseek(midiFile,0,SEEK_END );
lsize=ftell(midiFile);
rewind(midiFile);
buffer = (char*) malloc(sizeof(char)*lsize);
result = fread(buffer, 1, lsize, midiFile);
printf(buffer);
fclose(midiFile);
}
The first byte after MTHD is 0, so printf will only print MTHD since a C string ends with a zero byte. If you want to print the contents of the MIDI file you're going to need to convert the bytes of the file into hex.
I want to store data from desired byte upto another desired byte of the file opened in binary mode in to another file. Lets say file pointer is at byte# 10, now i want to read data from byte # 11 to byte # 30. I know i have to use fread() function but don't know how to tell this function to read from desired location upto another desired location. I am a beginner so bear answering this question.
I know fread() is C function, I want C++ equivalent functions for doing this work. A link or suggestion of book for learning file handling will be great!
Thanks alot for your help!
You have to seek:
std::ifstream infile("source.bin", std::ios::binary);
infile.seekg(10, std::ios::beg); // seek to 10 bytes from the beginning
char buf[20];
if (!infile.read(buf, 20)) { /* error */ }
// now your data is in buf
The stdio interface is is similar, but since this is C++, we prefer the iostreams one. You must never, ever use I/O operations without checking their return value, and in iostreams this is fairly easy. With fread you have to be careful to interpret the return value correctly.
Well, the prototype for fread is :
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
And fseek is:
int fseek ( FILE * stream, long int offset, int origin );
If you want to get to byte #11, you can do:
fseek(file, 11, SEEK_SET) // this means: go 11 bytes from the start position.
or, since you're already at byte 10, you can do:
fseek(file, 1, SEEK_CUR) // this means: go 1 byte beyond current position.
Then, to read up to byte 30 from byte 11, you need to read 19 bytes (30 - 11), so you do:
fread(buffer, sizeof(char), 19, file).
I am trying to use the system calls read() and write(). The following program creates a file and writes some data into it. Here is the code..
int main()
{
int fd;
open("student",O_CREAT,(mode_t)0600);
fd=open("student",O_WRONLY);
char data[128]="Hi nikhil, How are u?";
write(fd,data,128);
}
Upon the execution of the above program i got a file with name student created with size as 128 bytes.
int main()
{
int fd=open("student",O_WRONLY);
char data[128];
read(fd,data,128);
cout<<(char*)data<<endl;
}
But the output i get is junk characters....why is this so?
I wrote a small read program to read data from the file. Her is the code.
But the output
Don't read from a file that you've open in O_WRONLY mode!
Do yourself a favor and always check the return values of IO functions.
You should also always close file descriptors you've (successfully) opened. Might not matter for trivial code like this, but if you get into the habit of forgetting that, you'll end up writing code that leaks file descriptors, and that's a bad thing.
You're not checking whether read() returns an error. You should do so, because that's probably the case with the code in your question.
Since you're opening the file write-only in the first place, calling read() on it will result in an error. You should open the file for reading instead:
char data[128];
int fd = open("student", O_RDONLY);
if (fd != -1) {
if (read(fd, data, sizeof(data)) != -1) {
// Process data...
}
close(fd);
}
Well, one of the first things is that your data is not 128 bytes. Your data is the string: "Hi nikhil, How are u?", which is way less than 128 bytes. But you're writing 128 bytes from the array to the file. Everything after the initial string will be random junk from memory as the char array is only initialized with 21 bytes of data. So the next 107 bytes is junk.
This question already has answers here:
How to prevent scanf causing a buffer overflow in C?
(6 answers)
Closed 6 years ago.
I am trying to read in a certain portion of a file and that amount of data is different per line but I know how how many bytes of info I want. Like this:
5bytes.byte1byte2byte3byte4byte5CKSum //where # of bytes varies for each line (and there is no period only there for readability)
Actual data:
05AABBCCDDEE11
03AABBCC22
04AABBCCDD33
So I want to have my width be a variable like this:
fscanf_s(in_file,"%variableX", &iData);
Is this possible, because right now I'm thinking I have to create a case statement?
Unfortunately, no, there's no modifier like '*' for printf that causes scanf to get its field width or precision from a variable. The closest you can come is dynamically creating the format string:
char format[8];
sprintf(format, "%%%dX", width);
fscanf(in_file, format, &iData);
If you really want to be able to adjust the fscanf format programmatically, you could try stack-allocating a string with enough space, and then generating the format like so:
e.g.
char formatString[100];
// writes "%max_size[0-9]", substituting max_size with the proper digits
sprintf(formatString, "%%%d[0-9]", MAX_SIZE);
fscanf(fp, formatString, buffer); // etc...
fscanf with %X will stop at a newline automatically, right? If the fields really are newline-terminated (as in your example), then can't you just call
fscanf(in_file, "%X", &iData);
and let fscanf figure out where the end is?
You might also consider using C++ streams.
#include <ifstream>
#include <iostream>
// open the file and create a file input stream
ifstream file("test.txt" , ios::in | ios::binary);
// loop through the whole file
while (ifs.good())
{
// extract one byte as the field width
unsigned char width;
file.read(&width, 1);
// extract width number of unformatted bytes
char * bytes = new char[width];
file.read(bytes, width);
// process the bytes
...
delete [] bytes;
// skip EOL characters if needed
// file.seekg(1, ios_base::cur)
}
file.close();
A simpler way if the newlines are included as you seem to indicate, would be to use getLine(). Check out http://www.cplusplus.com/reference/iostream/ifstream/ for more ways to use read(), get(), getLine() and lots of other great stream functions.
I think the simplest would be to use fread() like this:
fread(buffer, nbytes, sizeof(char), in_file);