TGE Crashes with latest drivers on NVIDIA [FIX included]
by Fyodor -bank- Osokin · in Torque Game Engine · 11/18/2009 (10:18 am) · 10 replies
If you experience a crash on NVIDIA (mid/hi-end cards like GF GTX 285) + Vista/W7 using latest drivers, here is a way to solve it.
The problem is, that drivers reports a lot of supported extensions (like GL_ARB_depth_texture, GL_SGIS_generate_mipmap, GL_SUN_slice_accum, GL_WIN_swap_hint, etc), so the whole list does not fit the default buffer for Con::_printf().
Open console.cc
scroll down to this part (line 471 in stock TGE152):
Rebuild.
The problem is, that drivers reports a lot of supported extensions (like GL_ARB_depth_texture, GL_SGIS_generate_mipmap, GL_SUN_slice_accum, GL_WIN_swap_hint, etc), so the whole list does not fit the default buffer for Con::_printf().
Open console.cc
scroll down to this part (line 471 in stock TGE152):
static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, const char* fmt, va_list argptr)
{
char buffer[4096];
U32 offset = 0;
if(gEvalState.traceOn && gEvalState.stack.size())
...and change the buffer from 4096 to 8192, so we can handle large strings.Rebuild.
About the author
Game developer.
Recent Threads
#2
However, I'm not really satisfied with the solution provided as it doesn't really address the problem; just avoids it (for now). (Also, simply increasing the buffer size means wasting more memory space when printing smaller strings, which will be every other string)
So it sounds from your description like a buffer overrun issue, which I'd prefer to fix by implementing appropriately placed size checks rather than simply increasing the buffer size.
Unfortunately, I don't have access to a system like you describe to test this problem. And I am unable to reproduce a crash by simply feeding an oversized string to printf(). So I would like to ask if you have any more information about where and how this crash occurs?
11/19/2009 (12:32 pm)
This seems like a rather serious problem. Certainly something I must address in my game, since those high end cards are tomorrows mid-range cards and tomorrows cards are unlikely to have fewer supported extensions. However, I'm not really satisfied with the solution provided as it doesn't really address the problem; just avoids it (for now). (Also, simply increasing the buffer size means wasting more memory space when printing smaller strings, which will be every other string)
So it sounds from your description like a buffer overrun issue, which I'd prefer to fix by implementing appropriately placed size checks rather than simply increasing the buffer size.
Unfortunately, I don't have access to a system like you describe to test this problem. And I am unable to reproduce a crash by simply feeding an oversized string to printf(). So I would like to ask if you have any more information about where and how this crash occurs?
#3
I got crash on:
C2Q Q9550 + Windows7 x64 + GF 285 GFX + 191.07 drivers
the drivers reports the line that is 4292 bytes long or something like that (larger than 4096).
It really needs a proper fix to avoid such stuff. hopefully tomorrow I'll have a time to work on this.
11/19/2009 (12:38 pm)
yeah, I know it's not a solution really, but a quick hack..I got crash on:
C2Q Q9550 + Windows7 x64 + GF 285 GFX + 191.07 drivers
the drivers reports the line that is 4292 bytes long or something like that (larger than 4096).
It really needs a proper fix to avoid such stuff. hopefully tomorrow I'll have a time to work on this.
#4
11/19/2009 (1:08 pm)
Does TGE use it's own implementation of sprintf, or a wrapper around the system version? If it uses it's own, it shouldn't be too hard to make checks about the size before each substitution and if the subsitution would make the length go over the buffer length, allocate a new buffer with double the size.
#5
11/19/2009 (1:24 pm)
Looks like its just a wrapper around the system printfs on both Win and Linux. Could be why I can't reproduce a crash on my system. Perhaps the linux implementation checks the size where the Windows version does not?
#6
11/19/2009 (1:49 pm)
Ah hah! _printf uses dVsprintf which is just a wrapper around vsnprintf, and vsnprintf does NOT terminate the string when it fills the buffer! Which could lead to a crash later on when the string is read and copied into the console log.
#7
Now you could still consider adding a check in any function where you need the truncated data to increase the buffer size where necessary.
(edit: fixed error in code)
11/19/2009 (2:08 pm)
For starters.. I'm adding a check in dSprintf and dVsprintf to null terminate the strings if necessary.S32 dSprintf(char *buffer, U32 bufferSize, const char *format, ...)
{
va_list args;
va_start(args, format);
S32 len = vsnprintf(buffer, bufferSize, format, args);
if (bufferSize && len >= bufferSize)
buffer[bufferSize - 1] = '[[628787d924c23]]';
va_end(args);
return (len);
}
S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, void *arglist)
{
S32 len = vsnprintf(buffer, bufferSize, format, (char*)arglist);
if (bufferSize && len >= bufferSize)
buffer[bufferSize - 1] = ' ';
return (len);
}Now you could still consider adding a check in any function where you need the truncated data to increase the buffer size where necessary.
(edit: fixed error in code)
#9
11/19/2009 (3:53 pm)
hrmmm, you have doubled up your declaration of S32 len in dVsprintf. Which of those lines is the preferred method of doing it?
#10
... edit: made another fix. addition of bufferSize != 0 check to avoid crashing there if somehow you try to sprintf with a size of 0. Not that there should ever be a case where you want to call a sprintf with a size of 0, but it doesn't hurt to check.
11/19/2009 (4:30 pm)
oops! That was a copy/paste mistake. Copied an extra line from one function into the other. Fixed now.... edit: made another fix. addition of bufferSize != 0 check to avoid crashing there if somehow you try to sprintf with a size of 0. Not that there should ever be a case where you want to call a sprintf with a size of 0, but it doesn't hurt to check.
Torque 3D Owner Thomas -elfprince13- Dickerson