I'm trying to read data from a file but I'm getting a STATUS_STACK_BUFFER_OVERRUN error and the app crashes.
I have a struct:
struct BSPEntities
{
char* ents;
};
And I'm reading the file:
BSPEntities entities
ifstream mapfile;
int size = 54506;
int offset = 5182600;
entities.ents = new char[size];
mapfile.seekg(offset, ios::beg);
mapfile.read((char *)(&entities.ents), size);
"size" and "offset" are values loaded from the file and known to be valid. I have preprocessor directives #pragma pack(1) and #pragma push around the BSPEntities struct.
Thanks.
&entities.ents is a pointer to a pointer to char. The object pointed to (a pointer to char) is probably only 4 or 8 bytes depending on the architecture you're targeting, but you're trying to write 54,506 bytes to it. Obviously 54,506 is larger than 8, so you're writing past the end of the pointer, and the behavior is undefined.
That read should just be mapfile.read(entities.ents, size);
Also you don't need to mess around with #pragma pack here, unless there's something more complicated going on that you're not showing.
mapfile.read((char *)(&entities.ents), size);
Should be
mapfile.read(entities.ents, size);
Instead of passing the address of the heap memory block that ents points to, you are passing the address of ents itself. And since ents is being allocated on the stack, you are reading bytes onto the stack until it overruns.
Related
I'm having problems trying to save a struct to a new PE section and then reading.
The struct looks like:
#pragma pack(push, 1)
typedef struct _SCRIPT_STRUCT
{
DWORD dwKeySize;
unsigned char *lpKeyBuffer;
DWORD dwScriptSize;
unsigned char *lpScriptBuffer;
} SCRIPT, *PSCRIPT;
#pragma pack(pop)
lpKeyBuffer is a random hex values (0-255) array and lpScriptBuffer contains an encrypted (RC4) script (in Lua if that matters).
I think the struct is successfully written in the new section created but I can't read the buffers.
(Writting):
SCRIPT tScript;
tScript.dwKeySize = KEY_SIZE;
tScript.lpKeyBuffer = new unsigned char[tScript.dwKeySize];
GenerateKey(tScript.lpKeyBuffer, KEY_SIZE);
tScript.dwScriptSize = szScript.size();
tScript.lpScriptBuffer = new unsigned char[tScript.dwScriptSize];
memcpy(tScript.lpScriptBuffer, szScript.c_str(), tScript.dwScriptSize);
tScript.lpScriptBuffer = (unsigned char*)szScript.c_str();
rc4_encryption(tScript.lpScriptBuffer, tScript.dwScriptSize, tScript.lpKeyBuffer, tScript.dwKeySize);
DWORD dwScriptStructSize = sizeof(DWORD) + tScript.dwKeySize + sizeof(DWORD) + tScript.dwScriptSize;
char lpStructBuffer[dwScriptStructSize];
ZeroMemory(lpStructBuffer, dwScriptStructSize);
memcpy(lpStructBuffer, &tScript, dwScriptStructSize);
//CreateFile, create new section, etc
SetFilePointer(hCurrent, LastHeader->PointerToRawData, NULL, FILE_BEGIN);
WriteFile(hCurrent, lpStructBuffer, dwScriptStructSize, &dwRead, 0);
(Reading):
SCRIPT tScript;
memcpy(&tScript, lpScriptBuffer, dwSectionSize);
tScript.lpKeyBuffer = new unsigned char[tScript.dwKeySize];
tScript.lpKeyBuffer[tScript.dwKeySize] = 0x00;
tScript.lpScriptBuffer = new unsigned char[tScript.dwScriptSize];
tScript.lpScriptBuffer[tScript.dwScriptSize] = 0x00;
printf("dwScriptSize = %lu\n", tScript.dwScriptSize);
printf("dwKeySize = %lu\n", tScript.dwKeySize);
rc4_encryption(tScript.lpScriptBuffer, tScript.dwScriptSize, tScript.lpKeyBuffer, tScript.dwKeySize);
printf("script: %s\n", tScript.lpScriptBuffer);
The DWORD outputs are correct but the last printf shows strange symbols.
You can't save pointers to a file from one process, and read them from another process and expect it to work. Pointers are generally unique per process, especially to dynamically allocated data. When you read a pointer from a file from another process (even if it's the same program) that pointer will no longer point to the allocated data, it will just be a "random" stray pointer, and dereferencing it (like you do when printing it as a string) will lead to undefined behavior.
You need to save the string separately from the structure. When reading it's easy since you have the sizes of the variable-length data, and you know where (in relation to the structure) the data is saved.
The comment from shrike made me think and take a closer look at the code you present. It's not complete so this is all guess work, but the actual problem might actually be something different from what I described above.
Lets take a look at a few lines from your "reading" code (which doesn't actually show any reading):
SCRIPT tScript;
memcpy(&tScript, lpScriptBuffer, dwSectionSize);
tScript.lpKeyBuffer = new unsigned char[tScript.dwKeySize];
tScript.lpKeyBuffer[tScript.dwKeySize] = 0x00;
tScript.lpScriptBuffer = new unsigned char[tScript.dwScriptSize];
tScript.lpScriptBuffer[tScript.dwScriptSize] = 0x00;
Now assuming you read the structure into a character buffer lpScriptBuffer (similar to how you use one when writing, not really needed though), then you still have the same problem with the pointers I told about above, but there is another issue: You reassigning the pointers to point to some newly allocated memory. This is all well and good, but the problem here is that you don't actually try to initialize that memory. Not that you really can't with the code you show, but that's beside the point. The problem with you not initializing the memory is precisely that, it's uninitialized and therefore will have an indeterminate contents, seemingly random, and most likely not valid text. Using uninitialized memory is, like dereferencing stray pointers, undefined behavior.
There is also yet another issue: You writing out of bounds of the memory you allocate. As you hopefully knows, indexes in array are zero-based. So if you allocate size bytes then valid indexes are from (and including) 0 to size - 1.
Since you allocate e.g. tScript.dwKeySize bytes of memory then the top index is tScript.dwKeySize - 1 but then you use tScript.dwKeySize as index, which is out of bounds and again will lead to undefined behavior.
You need to allocate tScript.dwKeySize + 1 bytes instead, if the size doesn't already include the string terminator.
I am pretty inexperienced in C++ programming and now I'm trying to make a small program using dctmk to modify the pixel data of the dicom image. In doing so while reading documentation I found a c++ method about which I'm not quite clear. In the documention for the class DicomImage I found the following method:
int DicomImage::getOutputData ( void * buffer,
const unsigned long size,
const int bits = 0,
const unsigned long frame = 0,
const int planar = 0
)
My confusion is about buffer. It's quoted in the link as
buffer : pointer to memory buffer (must already be allocated)
Here my confusion is how do a I allocate? I'm not sure how I could allocate a memory that's a pointer of void type. Could you please explain. Thank you.
You can do it in the following way (for example):
void * mem = malloc(1024); // 1 kb
image.GetOutputData(mem, 1024);
// Don't forget to free(mem);
Another way:
char * mem = new char[1024];
image.GetOutputData((void *)mem, 1024);
// Don't forget to delete[] mem;
Another way:
char mem[1024];
image.GetOutputData((void *)&mem, 1024);
A pointer to void can point to anything, it's a generic nondescript anonymous pointer to some memory. This means that you can pass any kind of pointer as the first argument of the function, as all pointers can implicitly be converted to void*.
You can allocate any type of buffer. It will be converted using void*. However you will need to pass proper size of element. You will need to refer to documentation of api for size of each buffer element. In the example below it is 1 byte. And total buffer size is 10.
int size_of_buffer = 10;
unsigned char *buffer = malloc(sizeof(unsigned char)*size_of_buffer);
It looks like DicomImage::getOutputData does not care how you allocated your bytes. Simply take take the pointer to some blob of your choice (object, struct, array, whatever) and cast it to void*. You can get the memory with new, malloc or it can be a local variable.
Thing to be sure of:
Make sure you allocate enough space.
Make sure you accurately send the size parameter.
Make sure that you understand what format of data DicomImage::getOutputData works with.
I am looking for some ways to advance pointers to the beginning of files in compressed archives.
I have a character pointer to the beginning of the file that has been read into memory. The archive directory contains the offsets of each file. Is it legal/recommended to say:
char* beginning; //Imagine this is assigned to the beginning of the file in memory
int file1OffsetBytes = 1000; // Imagine the first file is 1000 bytes into the file
char* file1 = beginning + file1OffsetBytes;
Is this a bad idea? What is another way to do this?
that is quite Ok. You only have to take care about out of bounds jumps...
and one more thing: here is an size_t or ssize_t type usually used for memory buffers offset.
Adding to a pointer (or subtracting from it) is legal as long as the resulting pointer still points to an element in the array or to the non-existent element right after the last existing one. Needless to say, you can only dereference a pointer pointing to an existing element and the element has to have been initialized if you're reading it through the pointer.
I am using the cstdio (stdio.h) to read and write data from binary files. I have to use this library due to legacy code and it must be cross-platform compatible with Windows and Linux. I have a FILE* basefile_ which I use to read in the variables configLabelLength and configLabel, where configLabelLength tells me how much memory to allocate for configLabel.
unsigned int configLabelLength; // 4 bytes
char* configLabel = 0; // Variable length
fread((char *) &configLabelLength, 1, sizeof configLabelLength, baseFile_);
configLabel = new char[configLabelLength];
fread(configLabel,1, configLabelLength,baseFile_);
delete [] configLabel; // Free memory allocated for char array
configLabel = 0; // Be sure the deallocated memory isn't used
Is there a way to read in configLabel without using a pointer? For example is there a solution where I can use the c++ vector library or something where I do not have to worry about pointer memory management.
Just do:
unsigned int configLabelLength; // 4 bytes*
fread((char *) &configLabelLength, 1, sizeof configLabelLength, baseFile_);
std::vector<char> configLabel(configLabelLength);
fread(&configLabel[0], 1, configLabel.size(), baseFile_);
The elements in a vector are contiguous.
* I assume you know that unsigned int isn't necessary always 4 bytes. If you pay attention to your implementation details that's fine, but it'll be a bit easier if you adopt Boost's cstdint.hpp and just use uint32_t.
I need to be able to set the size of an array based on the number of bytes in a file.
For example, I want to do this:
// Obtain the file size.
fseek (fp, 0, SEEK_END);
size_t file_size = ftell(fp);
rewind(fp);
// Create the buffer to hold the file contents.
char buff[file_size];
However, I get a compile time error saying that the size of the buffer has to be a constant.
How can I accomplish this?
Use a vector.
std::vector<char> buff(file_size);
The entire vector is filled with '\0' first, automatically. But the performance "lost" might not be noticable. It's certainly safer and more comfortable. Then access it like a usual array. You may even pass the pointer to the data to legacy C functions
legacy(&buff[0]); // valid!
You should use a std::vector and not an array.
Real arrays require you to specify their size so that the compiler can create some space for them -- this is why the compiler complains when you don't supply a constant integer. Dynamic arrays are represented by a pointer to the base of the array -- and you have to retrieve the memory for the dynamic array yourself. You may then use the pointer with subscript notation. e.g.,
int * x;
x = (int *) malloc( sizeof(int) *
getAmountOfArrayElements() /* non-const result*/
);
x[5] = 10;
This leads to two types of problems:
Buffer over/under flows : you might subscript-index past either end of the array.
You might forget to release the memory.
Vector provides a nice little interface to hide these problems from you -- if used correctly.
Replace
char buff[file_size];
with
char *buff = new char[file_size];
and once the use of the buff is done..you can free the memory using:
delete[] buff;
There are two points in your question I'd like to cover.
The actual question, how do you create the array. Johannes answered this. You use a std::vector and create it with a size allocation.
Your error message. When you declare an array of some type, you must declare it with a constant size. So for example
const int FileSize = 1000;
// stuff
char buffer[FileSize];
is perfectly legitimate.
On the other hand, what you did, attempting to declare an array with variable size, and then not allocating with new, generates an error.
Problem is that buff needs be created on the heap (instead of stack). Compiler want s to know the exact size to create on the stack.
char* buff = new char[file_size];