Board index » cppbuilder » CodeGuard Access overrun

CodeGuard Access overrun


2006-07-01 02:38:24 AM
cppbuilder7
After doing a Version Query, I want to scan the data into 4 separate chunks
as follows:
if (VerQueryValue(aboutVerInfoBuffer, aboutVerBaseString.c_str(), &result,
&resultLen))
{
sscanf((char*)result, "%u.%u.%u.%u", &maj, &min, &rev, &bld);
}
where maj, min, rev, and bld are all unsigned ints and result is declared as
LPVOID.
At sscanf(), CodeGuard is giving me an Access overrun from an 'Attempt to
access 4 byte(s) at 0x0012F9F0, that is at offset 8 in local block
0x0012F9E8(=[ebp-0xA4] @Program1.exe:0x01:056A38) which is only 8 bytes
long.'
How can I fix this problem so that the access overrun will go away?
 
 

Re:CodeGuard Access overrun

If it helps, VerQueryValue returns "1.0.5.8" to LPVOID result.
 

Re:CodeGuard Access overrun

"poojo hackma" <poojo.com/mail>wrote in message
Quote
if (VerQueryValue(aboutVerInfoBuffer, aboutVerBaseString.c_str(), &result,
&resultLen))
{
sscanf((char*)result, "%u.%u.%u.%u", &maj, &min, &rev, &bld);
}
The character pointer that VerQueryValue() returns is not quaranteed to be
null-terminated. You need to use the resultLen value to know how long the
string actually, and then make a copy of the data when calling sscanf(), ie:
if( VerQueryValue(aboutVerInfoBuffer, aboutVerBaseString.c_str(),
&result, &resultLen) )
{
sscanf(AnsiString((char*)result, resultLen).c_str(), "%u.%u.%u.%u",
&maj, &min, &rev, &bld);
}
Quote
At sscanf(), CodeGuard is giving me an Access overrun from an
'Attempt to access 4 byte(s) at 0x0012F9F0, that is at offset 8 in local
block
Exactly my point. The returned pointer was not null-terminated, so sscanf()
tried to access memory that was outside of the character data.
Gambit
 

{smallsort}

Re:CodeGuard Access overrun

Thanks Gambit.
Now it looks like there is another CodeGuard error.
Values maj, min, rev, and bld are passed as follows:
int GetFileVersion(unsigned int &maj,
unsigned int &min,
unsigned int &rev,
unsigned int &bld)
{
unsigned int dummy[4];
<snip>
if (VerQueryValue(aboutVerInfoBuffer,
aboutVerBaseString.c_str(),
&result, &resultLen))
{
sscanf(AnsiString((char*)result, resultLen).c_str(),
"%u.%u.%u.%u",
&dummy[0], &dummy[1], &dummy[2], &dummy[3]);
maj = dummy[0];
min = dummy[1];
rev = dummy[2];
bld = dummy[3]; // <- CodeGuard: Attempt to access 2
// bytes that is offset 8 which is
// only 8 bytes long.
}
<snip>
}
Now CodeGuard does not like me assigning a value to bld.
Is there another key step I have overlooked?
 

Re:CodeGuard Access overrun

"poojo hackma" <poojo.com/mail>wrote in message
Quote
unsigned int dummy[4];
Why are you using that? Just use the parameters directly like you were
earlier. They are all references, so they will always point to valid
variables. You are not gaining anything at all by using a separate array.
Quote
bld = dummy[3]; // <- CodeGuard: Attempt to access 2
// bytes that is offset 8 which is
// only 8 bytes long.
There is no way that can be happening given the code you have shown.
Something else has to be happening. Either CodeGuard is reporting the wrong
code line to begin with, or you have another dummy or bld variable somewhere
that is being accessed instead of the ones you have shown here.
Gambit
 

Re:CodeGuard Access overrun

Quote
>unsigned int dummy[4];

Why are you using that? Just use the parameters directly like you were
earlier. They are all references, so they will always point to valid
variables. You are not gaining anything at all by using a separate array.
Just trying to debug exactly where the CodeGuard error is happening. I'll
change it back after this gets fixed.
Quote
>bld = dummy[3]; // <- CodeGuard: Attempt to access 2
>// bytes that is offset 8 which is
>// only 8 bytes long.

There is no way that can be happening given the code you have shown.
Something else has to be happening. Either CodeGuard is reporting the
wrong
code line to begin with, or you have another dummy or bld variable
somewhere
that is being accessed instead of the ones you have shown here.
Drats. Well, let me just paste in the entire little diddy. I think I
included all the info, but I could be mistaken.
//---------------------------------------------------------------------------
int TMainForm::GetFileVersion(INT_16U &maj, INT_16U &min,
INT_16U &rev, INT_16U &bld)
{
DWORD unused;
DWORD verSize;
LPVOID result;
char* ptr;
char* aboutVerInfoBuffer;
int i;
int iRet = 0;
unsigned int len;
unsigned int resultLen;
AnsiString aboutVerBaseString;
// First, get how big the VersionInfo buffer needs to be
// ParamStr(0) holds the complete path to the application
verSize = GetFileVersionInfoSize(ParamStr(0).c_str(), &unused);
if (verSize>0)
{
try
{
aboutVerInfoBuffer = new char[verSize + 1];
// Now, get the sort-of handle we'll use in further VerQueryValue
calls
if
(GetFileVersionInfo(ParamStr(0).c_str(),0,verSize,aboutVerInfoBuffer))
{ // Extract the language/translation information...
if (VerQueryValue(aboutVerInfoBuffer,
TEXT("\\VarFileInfo\\Translation"), &(void*)ptr, &len))
{ // ptr comes back as a ptr to two (16-bit) words containing the
two halves of
// the translation number required for StringFileInfo
aboutVerBaseString = AnsiString( "\\StringFileInfo\\")+
IntToHex(((WORD*)ptr)[0],4) +
IntToHex(((WORD*)ptr)[1],4) + "\\FileVersion";
if (VerQueryValue(aboutVerInfoBuffer, aboutVerBaseString.c_str(),
&result, &resultLen))
{
sscanf(AnsiString((char*)result, resultLen).c_str(),
"%u.%u.%u.%u", &maj, &min, &rev, &bld);
iRet = 1;
}
}
}
else {
AnsiString aErr = "GetFileVersion failed:\n" +
SysErrorMessage(::GetLastError());
MessageBox(Handle, aErr.c_str(), "GetFileVersion Error", MB_OK |
MB_ICONERROR);
}
}
__finally {
delete[] aboutVerInfoBuffer;
}
}
return iRet;
}
 

Re:CodeGuard Access overrun

"poojo hackma" <poojo.com/mail>wrote in message
Quote
Well, let me just paste in the entire little diddy.
Version numbers are stored in a language-independant manner as well as for
each locale. It is easier to pull them from the root '\' block instead of
from the 'Translation' table. You also don't need to use sscanf() anymore
if you do that. For example:
int TMainForm::GetFileVersion(INT_16U &maj, INT_16U &min, INT_16U &rev,
INT_16U &bld)
{
AnsiString strFile = ParamStr(0);
DWORD unused;
int iRet = 0;
DWORD verSize = GetFileVersionInfoSize(strFile.c_str(), &unused);
if( verSize>0 )
{
LPVOID verInfoBuffer = LocalAlloc(LMEM_FIXED, verSize);
if( verInfoBuffer )
{
if( GetFileVersionInfo(strFile.c_str(), unused, verSize,
verInfoBuffer) )
{
VS_FIXEDFILEINFO *verInfo = NULL;
UINT verLen;
if( VerQueryValue(verInfoBuffer, TEXT("\\"),
(void**)&verInfo, &verLen) )
{
maj = HIWORD(verInfo->dwFileVersionMS);
min = LOWORD(verInfo->dwFileVersionMS);
rev = HIWORD(verInfo->dwFileVersionLS);
bld = LOWORD(verInfo->dwFileVersionLS);
iRet = 1;
}
else
{
AnsiString aErr = "VerQueryValue failed:\n" +
SysErrorMessage(GetLastError());
MessageBox(Handle, aErr.c_str(), "GetFileVersion
Error", MB_OK | MB_ICONERROR);
}
}
else
{
AnsiString aErr = "GetFileVersionInfo failed:\n" +
SysErrorMessage(GetLastError());
MessageBox(Handle, aErr.c_str(), "GetFileVersion Error",
MB_OK | MB_ICONERROR);
}
LocalFree(verInfoBuffer);
}
else
{
AnsiString aErr = "LocalAlloc failed:\n" +
SysErrorMessage(GetLastError());
MessageBox(Handle, aErr.c_str(), "GetFileVersion Error",
MB_OK | MB_ICONERROR);
}
}
return iRet;
}
Gambit
 

Re:CodeGuard Access overrun

Just some problems I notice in your code - I'm afraid the list is not
exhaustive.
"poojo hackma" <poojo.com/mail>writes:
Quote
int TMainForm::GetFileVersion(INT_16U &maj, INT_16U &min,
INT_16U &rev, INT_16U &bld)
{
DWORD unused;
DWORD verSize;
LPVOID result;
char* ptr;
char* aboutVerInfoBuffer;
int i;
int iRet = 0;
unsigned int len;
unsigned int resultLen;
AnsiString aboutVerBaseString;
Functions with that many local variables are too long. This variable
definition list is longer that an entire function should be in total
IMHO.
Also, prefer to define variables where you need them and where you
know how to initialize them.
Quote

// First, get how big the VersionInfo buffer needs to be
// ParamStr(0) holds the complete path to the application
verSize = GetFileVersionInfoSize(ParamStr(0).c_str(), &unused);

if (verSize>0)
{
try
{
aboutVerInfoBuffer = new char[verSize + 1];
If you use a std::vector<char>instead, you can get rid of the try and
__finally scaffolding.
Quote
if (VerQueryValue(aboutVerInfoBuffer,
TEXT("\\VarFileInfo\\Translation"), &(void*)ptr, &len))
&(void*)ptr looks very fishy. (void*)ptr is an rvalue, so taking its
address most likely does not what you expect it does.
Quote
sscanf(AnsiString((char*)result, resultLen).c_str(),
"%u.%u.%u.%u", &maj, &min, &rev, &bld);
1) I don't like c_str() applied to a temporary object.
2) sscanf() returns a value that you should inspect before reading
maj, min, rev and bld.
E.g.:
std::string const tmp(static_cast<char *>(result),resultLen);
if (sscanf(tmp.c_str(),"%u.%u.%u.%u", &maj, &min, &rev, &bld)==4)
; // use maj, min, rev, bld
else
; // deal with conversion failure
 

Re:CodeGuard Access overrun

"Thomas Maeder [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
1) I don't like c_str() applied to a temporary object.
That does not make it invalid, though. The temporary is valid until the
call to sscanf() is complete.
Gambit