C++ function call results in garbage parameters - c++

ASI have a C++ function that looks like this:
static const unsigned int unknown = (unsigned)-1;
static inline char *
duplicateStringValue( const char *value,
unsigned int length = unknown )
{
if ( length == unknown )
length = (unsigned int)strlen(value);
char *newString = static_cast<char *>( malloc( length + 1 ) );
ASSERT( newString != 0, "Failed to allocate string value buffer" );
memcpy( newString, value, length );
newString[length] = 0;
return newString;
}
(This happens to be in the jsoncpp library, but I'm pretty sure that's orthogonal to the problem)
The issue is that according to GDB, the function is arriving on the stack with parameters ("", 31135568). The program tries and fails to allocate 31 megabytes, hits the assert and dies.
By examining the frame above dulpicateStringValue() with GDB, I can see that it is being invoked with the first parameter pointing to a small string on the heap, and the second parameter left out. In other words, as far as I can tell the function call is incorrectly getting garbage values for parameters.
I'm truly stumped by this. The only idea I have is that dulpicateStringValue() is called many times before this successfully, but at this point the stack is ~25 frames deep, much deeper than usual (as far as I can tell). Perhaps the stack and the heap are colliding and scribbling all over each other?
If anyone has some insights or has encountered something similar, I'd love to hear about it.
Edit: In response to questions, the function is being called as
value_.string_ = duplicateStringValue( other.value_.string_ );
where other.value_ is a union described by GDB as
value_ = {int_ = 34536679944, uint_ = 34536679944,
real_ = 1.7063387081744787e-313, bool_ = 8,
string_ = 0x80a8bea08 "boolean", map_ = 0x80a8bea08}
The code for the union:
union ValueHolder
{
LargestInt int_;
LargestUInt uint_;
double real_;
bool bool_;
char *string_;
ObjectValues *map_;
} value_;
Edit 2: #MarkRansom asked how the parameters are getting on the stack. In fact, they're not, GDB is reading them straight out of the register:
(gdb) f 1
#1 0x000000080663377e in duplicateStringValue (value=0x80aac9a10 "", length=31135568) at json_value.cpp:60
60 ASSERT( newString != 0, "Failed to allocate string value buffer" );
(gdb) p &length
Address requested for identifier "length" which is in register $rsi
(gdb) p &value
Address requested for identifier "value" which is in register $r13

Related

Does this Microsoft CFileDialog example lead to a potential memory violation

I've been experiencing a number of random crashes using the MFC CFileDialog class so I had a look at their example code from this page which reads as follows;
#define MAX_CFileDialog_FILE_COUNT 99
#define FILE_LIST_BUFFER_SIZE ((MAX_CFileDialog_FILE_COUNT * (MAX_PATH + 1)) + 1)
CString fileName;
wchar_t* p = fileName.GetBuffer( FILE_LIST_BUFFER_SIZE );
CFileDialog dlgFile(TRUE);
OPENFILENAME& ofn = dlgFile.GetOFN( );
ofn.Flags |= OFN_ALLOWMULTISELECT;
ofn.lpstrFile = p;
ofn.nMaxFile = FILE_LIST_BUFFER_SIZE;
dlgFile.DoModal();
fileName.ReleaseBuffer();
wchar_t* pBufEnd = p + FILE_LIST_BUFFER_SIZE - 2;
wchar_t* start = p;
while( ( p < pBufEnd ) && ( *p ) )
p++;
if( p > start )
{
_tprintf(_T("Path to folder where files were selected: %s\r\n\r\n"), start );
p++;
int fileCount = 1;
while( ( p < pBufEnd ) && ( *p ) )
{
start = p;
while( ( p < pBufEnd ) && ( *p ) )
p++;
if( p > start )
_tprintf(_T("%2d. %s\r\n"), fileCount, start );
p++;
fileCount++;
}
}
By my reading of it, the statement fileName.ReleaseBuffer(); makes the memory pointed to in the buffer variable pinvalid, such that the remaining code is liable to experience memory violations. At the same time, I'd also assume that Microsoft would have checked such examples prior to publishing them. Am I missing something obvious here? Is there any reason for the use of a CString here over a simple new followed by a delete after the buffer is no longer required?
Sample code isn't formal documentation. This sample is wrong. The documentation is right:
The address returned by GetBuffer may not be valid after the call to ReleaseBuffer because additional CSimpleStringT operations can cause the CSimpleStringT buffer to be reallocated.
The sample uses CString (over raw pointers and manual memory management) for automatic memory management and exception safety. The latter is a lot harder to get right with manual memory management (although this sample doesn't get exception safety right, either).
If you want to fix the sample code to adhere to the contract, the following changes need to be made:*
Replace wchar_t* pBufEnd = p + FILE_LIST_BUFFER_SIZE - 2; with const wchar_t* pBufEnd = fileName.GetString() + FILE_LIST_BUFFER_SIZE - 2;.
Replace wchar_t* start = p; with const wchar_t* start = fileName.GetString();
Replace all remaining occurrences of p in the code after the dialog invocation with a new variable, initialized as const wchar_t* current = fileName.GetString();).
This is a common error. Whenever a developer thinks they need a char* of sorts, they overlook that they need a const char* instead, which pretty much every string type supplies by means of a member function.
Note that there are other bugs in the sample code, that have not been explicitly addressed in this answer (like the mismatch of character types as explained in another answer).
* A C++ implementation that retrieves the list of selected files can be found in this answer.
You might be noticing a difference between specification and implementation. The code above works because the CString implementation allows it, even though the CString specification bans it.
And to highlight the quality of the example: it mixes TCHAR and wchar_t. In tprintf("%s", start) the string start has to be a TCHAR* but the example uses wchar_t* start

invalid operands to binary *

typedef struct pixel_type
{
unsigned char r;
unsigned char g;
unsigned char b;
} pixel;
buffer = (int *) malloc (sizeof(pixel) * stdin );
I keep getting an error that says "invalid operands to binary *(have unsigned int' and 'struct _IO_FILE *)." The struct is defined outside of a function so it is universal. The buffer is defined within the main. I can provide more code if needed. What is my problem?
EDIT: Alright so apparently I was a little confusing. What I'm trying to do is pass a file in, and then malloc enough space for that file. I was thinking of using a FILE function to pass the file in, and then using that, but was hoping to just use "stdin" instead. Is this not allowed? And this is in C. Just tagged C++ hoping someone else might see a similar problem.
Sorry for the silly question. Not new to C as a whole, but new to malloc. Second year student :P
I think you want to read the number of pixels from stdin:
int n;
scanf("%d", &n);
and then allocate memory for that many pixels:
unsigned char * buffer = (unsigned char *) malloc (sizeof(pixel) * n );
The right way to allocate the memory would be something like
size_t elements = 0;
... // get the number of elements as a separate operation
pixel *buffer = malloc( sizeof *buffer * elements ); // note no cast,
// operand of sizeof
if ( buffer )
{
// load your buffer here
}
In C, casting the result of malloc is considered bad practice1. It's unnecessary, since values of void * can be assigned to any pointer type, and under C89 compilers it can suppress a diagnostic if you forget to include stdlib.h or otherwise don't have a declaration for malloc in scope.
Also, since the expression *buffer has type pixel, the expression sizeof *buffer is equivalent to sizeof (pixel). This can save you some maintenance time if the type of buffer ever changes.
How you get the number of elements for your array really depends on your application. The easiest way would be to stick that value at the head of your data file:
size_t elements = 0;
FILE *data = fopen( "pixels.dat", "r" );
if ( !data )
{
// You will want to add real error handling here.
exit( 0 );
}
if ( fscanf( data, "%zu", &elements ) != 1 )
{
// You will want to add real error handling here
exit( 0 );
}
pixel *buffer = malloc( sizeof *buffer * elements );
if ( buffer )
{
for ( size_t i = 0; i < elements; i++ )
{
if ( fscanf( data, "%hhu %hhu %hhu", // %hhu for unsigned char
&buffer[i].r, &buffer[i].g, &buffer[i].b ) != 3 )
{
// more real error handling here
exit( 0 );
}
}
}
Naturally, this assumes that your data file is structured as rows of 3 integer values, like
10 20 30
40 50 60
etc.
1. As opposed to C++, where it's required, but if you're writing C++ you should be using the new operator anyway. Yes, you will see thousands of examples that include the cast. You will also see thousands of examples that use void main(). Most C references are simply crap.

Segmentation fault : Address out of bounds for a pointer in C

I am trying to build and run some complicated code that was written by someone else, I don't know who they are and can't ask them to help. The code reads a bpf (brain potential file) and converts it to a readable ascii format. It has 3 C files, and 2 corresponding header files. I got it to build successfully with minor changes, however now it crashes
with a segmentation fault.
I narrowed the problem down to FindSectionEnd() (in ReadBPFHeader.c) and find that the error occurs when sscanfLine() (in the file sscanfLine.c) is called (code for both is below).
ui1 is defined as unsigned char.
si1 is defined as char.
Just before returning from sscanfLine(), the address pointed to by dp is 0x7e5191, or something similar ending with 191. However, on returning to FindSectionEnd(), dp points to 0x20303035 and it says 'Address 0x20303035 is out of bounds', which then causes a fault at strstr(). The loop in FindSectionEnd() runs without problem for 14 iterations before the fault occurs. I have no idea what is going wrong. I really hope the information I have given here is adequate.
ui1 *FindSectionEnd(ui1 *dp)
{
si1 Line[256], String[256];
int cnt=0;
while (sscanfLine(dp, Line) != EOF){
dp = (ui1 *)strstr(dp, Line);
dp+= strlen(Line);
sscanf(Line,"%s",String);
if(SectionEnd(String))
return(dp);
}
return(NULL);
}
si1 *sscanfLine(ui1 *dp, si1 *s)
{
int i = 0;
*s = NULL;
int cnt = 0;
while (sscanf(dp, "%c", s + i) != EOF){
cnt++;
dp++;
if(*(s + i) == '\n') {
*(s + i + 1) = '\0';
return s;
}
++i;
}
*(s + i) = '\0';
return s;
}
The sscanfLine function doesn't respect the size of the buffer passed in, and if it doesn't find '\n' within the first 256 bytes, happily trashes the stack next to the Line array.
You may be able to work around this by making Line bigger.
If you're going to improve the code, you should pass the buffer size to sscanfLine and make it stop when the count is reached even if a newline wasn't found. While you're at it, instead of returning s, which the caller already has, make sscanfLine return the new value of dp, which will save the caller from needing to use strstr and strlen.
My first guess would be that your string is not null terminated and strstr() segfaults because it reads past the boundaries of the array

Null Pointer issue using string::iterator in Visual Studio 2005

I am working with some legacy code. The legacy code works in production mode in the following scenario. I'm trying to build a command line version of the legacy code for testing purposes. I suspect there is an environmental setting issue at work here, but I'm relatively new to C++ and Visual Studio (long time eclipse/java guy).
This code is attempting to read in a string from a stream. It reads in a short, which in my debug scenario has a value of 11. Then, it is supposed to read in 11 chars. But this code craps out on the first char. Specifically, in the read method below, ptr is null, and so the fread call is throwing an exception. Why is ptr NULL?
Point of clarification, ptr becomes null between the operator>>(string) and operator>>(char) calls.
Mystream& Mystream::operator>>( string& str )
{
string::iterator it;
short length;
*this >> length;
if( length >= 0 )
{
str.resize( length );
for ( it = str.begin(); it != str.end(); ++it )
{
*this >> *it;
}
}
return *this;
}
The method for reading the short is here and looking at the file buffer etc. this looks like it is working properly.
Mystream& Mystream::operator>>(short& n )
{
read( ( char* )&n, sizeof( n ) );
SwapBytes( *this, ( char* )&n, sizeof( n ) );
return *this;
}
Now, the method for reading in a char is here:
Mystream& Mystream::operator>>(char& n )
{
read( ( char* )&n, sizeof( n ) );
return *this;
}
and the read method is:
Mystream& Mystream::read( char* ptr, int n )
{
fread( (void*)ptr, (size_t)1, (size_t)n, fp );
return *this;
}
One thing I don't understand, in the string input method, the *it is a char right? So why does the operator>>(char &n) method get dispatched on that line? In the debugger, it looks like the *it is a 0, (although a colleague tells me he doesn't trust the 2005 debugger on such things) and thus, it looks like the &n is treated as a null pointer and so the read method is throwing an exception.
Any insights you can provide would be most helpful!
Thanks
John
ps. For the curious, Swap Bytes looks like this:
inline void SwapBytes( Mystream& bfs, char * ptr, int nbyte, int nelem = 1)
{
// do we need to swap bytes?
if( bfs.byteOrder() != SYSBYTEORDER )
DoSwapBytesReally( bfs, ptr, nbyte, nelem );
}
And DoSwapBytesReally looks like:
void DoSwapBytesReally( Mystream& bfs, char * ptr, int nbyte, int nelem )
{
// if the byte order of the file
// does not match the system byte order
// then the bytes should be swapped
int i, n;
char temp;
#ifndef _DOSPOINTERS_
char *ptr1, *ptr2;
#else _DOSPOINTERS_
char huge *ptr1, huge *ptr2;
#endif _DOSPOINTERS_
int nbyte2;
nbyte2 = nbyte/2;
for ( n = 0; n < nelem; n++ )
{
ptr1 = ptr;
ptr2 = ptr1 + nbyte - 1;
for ( i = 0; i < nbyte2; i++ )
{
temp = *ptr1;
*ptr1++ = *ptr2;
*ptr2-- = temp;
}
ptr += nbyte;
}
}
I'd throw out this mess and start over. Extrapolating from the code, if what you had actually worked, it would be roughly equivalent to something like this:
MyStream::operator>>(string &s) {
short size;
fread((void *)&size, sizeof(size), 1, fP);
size = ntohs(size); // oops: after reading edited question, this is really wrong.
s.resize(size);
fread((void *)&s[0], 1, size, fp);
return *this;
}
In this case, delegating most of the work to other functions doesn't seem to have gained much -- this does the work more directly, but still isn't significantly longer or more complex than the original (if anything, I'd say rather the opposite).
I found a gray beard in the company who could explain what's going on to me. (I had already spoken to 2 old timers so I figured I had covered the old timer avenue of attack.) The code above is not ANSI compliant STL code. In Visual Studio 2005, Microsoft first introduced STL and there were issues. In particular older code that used to work would now fail in 2005 (I think 64bit mode may play a role in this as well.) Because of this, code will not work in debug mode (but it will work in release mode). One partial article is located here.
http://msdn.microsoft.com/en-us/library/aa985982%28v=vs.80%29.aspx
The particular issue I saw has to do with the line: it = str.begin() in the first method in the question. str is an empty string. So str.begin() is technically not defined. Visual Studio treats this situation differently between debug and release modes. (Can't do this in debug, you can do it in release.)
Bottom line, the gray beard suggested rewrite was exactly Jerry's. Ironically, the gray beard had fixed this problem in several files, but neglected to check it into the mainline. Uh oh. That scares the &#$!! out of me.

Realloc returning null?

I allocate some memory with malloc - about 128 bytes.
Later on, I call realloc with about 200 bytes, but it's returning null!
It returns a valid pointer if I do free, and then another malloc, however I would like to use realloc.
What could explain this behavior (I clearly am not running out of memory)? Is this valid behavior?
Code bits:
//class constructor
size = 0;
sizeAllocated = DEFAULT_BUFFER_SIZE; //64
data = (char*)malloc(sizeAllocated * sizeof(char)); //data is valid ptr now, I've checked it
data[0] = '\0';
//later on:
//append function
bool append(char** data, const char* str, size_t strLen) {
if((size + strLen) >= sizeAllocated) {
sizeAllocated += strLen + 1 + BUFFER_ALLOCATION_STEP;
char* temp = realloc(*data, sizeAllocated * sizeof(char));
if(temp)
*data = temp;
return( temp != NULL );
}
EDIT: fixed. I was overloading the << operator for my class, and had it return *this instead of void. Somehow this was screwing everything up! If anyone could explain why this happen, it would be nice!
Since the following comment was added to the question
data = (char*)realloc(data, (size_t)(sizeAllocated * sizeof(char)));
if I replace sizeAllocated with a
constant that is same value, it
reallocs correctly
Now we can figure out what happened. You replaced sizeAllocated with a constant that DID NOT have the same value. For debugging purposes, add a statement that will output the value of sizeAllocated and you will be surprised.