Reading text file cause invalid character at buffer end - c++

Reading a simple text file in c++ display invalid characters at the end of buffer,
string filecontent="";
ifstream reader(fileName);
reader.seekg (0, reader.end);``
int length = reader.tellg();
reader.seekg (0, reader.beg);
char *buffer=new char[length];
reader.read(buffer,length);
filecontent=buffer;
reader.close();
cout<<"File Contents"<<std::endl;
cout<<filecontent;
delete buffer;
return false;
but when i specify buffer length incremented by one ie
char *buffer=new char[length+1];
reader.read(buffer,length+1);
it works fine without invalid characters i want to know what is the reason behind this?

You read a string without terminating it with a trailing zero (char(0) or '\0'). Increase the buffer length by one and store a zero at buffer[reader.tellg()]. Just increasing the buffer size is not good enough, you might get a trailing zero by accident.

Related

Load shellcode from file to char* comes strange characters in end of text

I have a char array[] and is like following:
// MessageBox
char xcode[] = "\x31\xc9\x64\x8b\x41\x30\x8b\x40\xc\x8b\x70\x14\xad\x96\xad\x8b\x58\x10\x8b\x53\x3c\x1\xda\x8b\x52\x78\x1\xda\x8b\x72\x20\x1\xde\x31\xc9\x41\xad\x1\xd8\x81\x38\x47\x65\x74\x50\x75\xf4\x81\x78\x4\x72\x6f\x63\x41\x75\xeb\x81\x78\x8\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x1\xde\x66\x8b\xc\x4e\x49\x8b\x72\x1c\x1\xde\x8b\x14\x8e\x1\xda\x31\xc9\x53\x52\x51\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd2\x83\xc4\xc\x59\x50\x51\x66\xb9\x6c\x6c\x51\x68\x33\x32\x2e\x64\x68\x75\x73\x65\x72\x54\xff\xd0\x83\xc4\x10\x8b\x54\x24\x4\xb9\x6f\x78\x41\x0\x51\x68\x61\x67\x65\x42\x68\x4d\x65\x73\x73\x54\x50\xff\xd2\x83\xc4\x10\x68\x61\x62\x63\x64\x83\x6c\x24\x3\x64\x89\xe6\x31\xc9\x51\x56\x56\x51\xff\xd0";
Then i had inserted all this content of variable above into a file (file with UTF-8 format and content without the "") and tried load this way:
ifstream infile;
infile.open("shellcode.bin", std::ios::in | std::ios::binary);
infile.seekg(0, std::ios::end);
size_t file_size_in_byte = infile.tellg();
char* xcode = (char*)malloc(sizeof(char) * file_size_in_byte);
infile.seekg(0, std::ios::beg);
infile.read(xcode, file_size_in_byte);
printf("%s\n", xcode); // << prints content of xcode after load from file
if (infile.eof()) {
size_t bytes_really_read = infile.gcount();
}
else if (infile.fail()) {
}
infile.close();
I'm seeing some strange characters in end of text see:
What is need to fix it?
The issue is that the printf format specifier "%s" requires that the string is null-terminated. In your case, the null-terminator just happens to be after those characters you're seeing, but nothing guarantees where the null is unless you put one there.
Since you're using C++, one way to print the characters is to use the write() function available for streams:
#include <iostream>
//...
std::cout.write(xcode, file_size_in_bytes);
The overall point is this -- if you have a character array that is not null-terminated and contains data, you must either:
Put the null in the right place before using the array in functions that look for the null-terminator or
Use functions that state how many characters to process from the character array.
The answer above uses item 2.

C++ char buffer pointer error

I'm using a function that reads a spooled file and sets a buffer with the output.
The function returns OK state and sets readBytes correctly. It also notifies that the reading operation has reached the end of the file.
char* splFileContent = new char[3000];
ULONG readBytes;
int z = cwbOBJ_ReadSplF(splFile, splFileContent, 500, &readBytes, 0);
//z value is REACHED END OF FILE or OK if read but didn't reach the end of the file.
The trouble comes when trying to convert the char buffer to string, I'm getting "4Ä" as string value...
I convert the char buffer to string this way:
stringstream s;
s << splFileContent;
string bufferContent = s.str();
What I'm doing wrong?
It looks like splFileContent is binary content and not printable characters.
The start of the file may contain a BOM of some sort, e.g. unicode indicator. If it is, you should read in the BOM first and then the rest of the file.
Note: unless the file read function here adds a NULL, be sure to append one as well.

Reading binary text into array?

I have a program that I need to read binary text into. I read the binary text via a redirection:
readData will be an executable made by my Makefile.
Example: readData < binaryText.txt
What I want to do is read the binary text, and store each character in the binary text file as a character inside a char array. The binary text is made up of 32 This is my attempt at doing so...
unsigned char * buffer;
char d;
cin.seekg(0, ios::end);
int length = cin.tellg();
cin.seekg(0, ios::beg);
buffer = new unsigned char [length];
while(cin.get(d))
{
cin.read((char*)&buffer, length);
cout << buffer[(int)d] << endl;
}
However, I keep getting a segmentation fault on this. Might anyone have any ideas on how to read binary text into a char array? Thanks!
I'm more a C programmer rather than a C++, but I think that you should have started your while loop
while(cin.get(&d)){
The easiest would be like this:
std::istringstream iss;
iss << std::cin.rdbuf();
// now use iss.str()
Or, all in one line:
std::string data(static_cast<std::istringstream&>(std::istringstream() << std::cin.rdbuf()).str());
Something like this should do the trick.
You retrieve the filename from the arguments and then read the whole file in one shot.
const char *filename = argv[0];
vector<char> buffer;
// open the stream
std::ifstream is(filename);
// determine the file length
is.seekg(0, ios_base::end);
std::size_t size = is.tellg();
is.seekg(0, std::ios_base::beg);
// make sure we have enough memory space
buffer.reserve(size);
buffer.resize(size, 0);
// load the data
is.read((char *) &buffer[0], size);
// close the file
is.close();
You then just need to iterate over the vector to read characters.
The reason why you are getting segmentation fault is because you are trying to access an array variable using a character value.
Problem:
buffer[(int)d] //d is a ASCII character value, and if the value exceeds the array's range, there comes the segfault.
If what you want is an character array, you already have that from cin.read()
Solution:
cin.read(reinterpret_cast<char*>(buffer), length);
If you want to print out, just use printf
printf("%s", buffer);
I used reinterpret_cast because it thought it is safe to convert to signed character pointer since most characters that are used would range from 0 ~ 127. You should know that character values from 128 to 255 would be converted wrongly.

reading buffer C++

I'm trying to read buffer in C++ one character at the time until '\n', and initialize char array with these characters using do-while loop. I know I could use cin.getline(), but I want to try it on my own.
int main()
{
char buffer [1024];
int index = 0;
char temp;
do
{
cin.get( temp );
buffer [ index ] = temp;
index ++;
}
while ( temp != '\n' );
cout << buffer << endl;
return 0;
}
It gives me incorrect result-the proper text fallow by couple of lines of squre brackets mixed with other weird symbols.
At first, after whole text you have to append '\0' as end of string
it should look like buffer[ index ] = 0; because you should rewrite your \n character which you append too.
Of course, there are other things which you should check but they are not your main problem
length of your input because you have limited buffer - max length is 1023 + null byte
end of standard input cin.eof()
You're not null-delimiting your buffer.
Try to change the first line to
char buffer[1024] = "";
This will set all characters in buffer to 0. Or, alternatively, set only the last character to 0, by doing
buffer[index] = 0;
after the loop.
Also, (as correctly pointed by others) if the text is longer than 1024 characters, you'll have a buffer overrun error - one of the most often exploited causes for security issues in software.
Two things:
If the length of the line you are
reading exceeds 1024 you write past
the buffer which is bad.
If the length is within the
limit,you are not terminating the
string with null char.
You can trying doing it the following way. This way if you find a fine exceeding the buffer size, we truncate it and also add the null char at the end ouside the loop.
#define MAX 1024
int main()
{
char buffer [MAX];
int index = 0;
char temp;
do
{
// buffer full.
if(index == MAX-1)
break;
cin.get( temp );
buffer [ index ] = temp;
index ++;
}
while ( temp != '\n' );
// add null char at the end.
buffer[index] = '\0';
cout << buffer << endl;
return 0;
}
Several issues I noted:
(1) What character encoding is the input. You could be reading 8,16, or 32 bit characters. Are you sure you're reading ASCII?
(2) You are searching for '\n' the end of line character could be '\r\n' or '\r' or '\n' depending on your platform. Perhaps the \r character by itself is your square bracket?
You stop filling the buffer when you get to a newline, so the rest is uninitialised. You can zero-initialise your buffer by defining it with: char buffer[1024] = {0}; This will fix your problem.
You are not putting a '\0' at the end of the string. Additionally, you should really check for buffer overflow conditions. Stop reading when index gets to 1024.

Reading std::string from binary file

I have a couple of functions I created a while ago for reading and writing std::strings to a FILE* opened for reading in binary mode. They have worked fine before (and WriteString() still works) but ReadString() keeps giving me memory corruption errors at run-time. The strings are stored by writing their size as an unsigned int before the string data as char.
bool WriteString(std::string t_str, FILE* t_fp) {
// Does the file stream exist and is it valid? If not, return false.
if (t_fp == NULL) return false;
// Create char pointer from string.
char* text = const_cast<char*>(t_str.c_str());
// Find the length of the string.
unsigned int size = t_str.size();
// Write the string's size to the file.
fwrite(&size, sizeof(unsigned int), 1, t_fp);
// Followed by the string itself.
fwrite(text, 1, size, t_fp);
// Everything worked, so return true.
return true;
}
std::string ReadString(FILE* t_fp) {
// Does the file stream exist and is it valid? If not, return false.
if (t_fp == NULL) return false;
// Create new string object to store the retrieved text and to return to the calling function.
std::string str;
// Create a char pointer for temporary storage.
char* text = new char;
// UInt for storing the string's size.
unsigned int size;
// Read the size of the string from the file and store it in size.
fread(&size, sizeof(unsigned int), 1, t_fp);
// Read [size] number of characters from the string and store them in text.
fread(text, 1, size, t_fp);
// Store the contents of text in str.
str = text;
// Resize str to match the size else we get extra cruft (line endings methinks).
str.resize(size);
// Finally, return the string to the calling function.
return str;
}
Can anyone see any problems with this code or have any alternative suggestions?
Biggest major problem that jumped out at me:
// Create a char pointer for temporary storage.
char* text = new char;
// ...
// Read [size] number of characters from the string and store them in text.
fread(text, 1, size, t_fp);
This creates text as a pointer to a single character, and then you try to read an arbitrary number of characters (potentially many more than one) into it. In order for this to work right, you would have to create text as an array of characters after you figured out what the size was, like this:
// UInt for storing the string's size.
unsigned int size;
// Read the size of the string from the file and store it in size.
fread(&size, sizeof(unsigned int), 1, t_fp);
// Create a char pointer for temporary storage.
char* text = new char[size];
// Read [size] number of characters from the string and store them in text.
fread(text, 1, size, t_fp);
Second, you don't free the memory that you allocated to text. You need to do that:
// Free the temporary storage
delete[] text;
Finally, is there a good reason why you are choosing to use C file I/O in C++? Using C++-style iostreams would have alleviated all of this and made your code much, much shorter and more readable.
The problem is:
char* text = new char;
you're allocating a single character. Do the allocation after you know size, and allocate all the size characters you need (e.g. with a new char[size]). (To avoid a leak, del it later after copying it, of course).
I'm sorry but the chosen answer doesn't work for me.
// UInt for storing the string's size.
unsigned int size;
// Read the size of the string from the file and store it in size.
fread(&size, sizeof(unsigned int), 1, t_fp);
// Create a char pointer for temporary storage.
char* text = new char[size];
// Read [size] number of characters from the string and store them in text.
fread(text, 1, size, t_fp);
The size ends up being a very large number. Am I missing something?