Hi,
One part of my application opens up a set of files using _findfirst, _findnext and _stat to see their current date using VC++ 2005. This code has been working fine and noone had any problems.
However now I got a request from a user saying some of his files were dated year 1617 and that the application crashed. The crash address indicates that it happens within the CRT code of these functions but due to the circumstances I don't know (yet) which of them.
The exception code given is 0xc000000d. For now the user removed the broken files and everything went back to a working state. I however tried to see if I used the functions in a wrong way and did not use the right error returncodes. However after verifying by documentation everything seems ok on my part.
The next logical step is to try to reproduce this problem and see if it's the CRT which is broken in this regard. For now I've been unable to do so since it seems that Windows itself cannot handle dates before 1980 and the most of the CRT api functions only goes back to 1970.
Are there any way to create files this old in order to re-produce this problem So far indications show that it's a problem in the CRT but the crashing instruction is a "add esp, 14h". This does not make any sense to me though as it's just an addition to a stack variable. However it could be that the stack is off for some reason due to the bad date.
Thanks in advance.
-- Henrik

_findfirst, _findnext and _stat problem
Hooper
You can reproduce this easily with the following code:
FILETIME time;
time.dwLowDateTime = 1;
time.dwHighDateTime = 1;
HANDLE hFile = CreateFile(_T("D:\\Projects\\stdafx.cpp"), FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, NULL);
SetFileTime(hFile, &time, &time, &time);
CloseHandle(hFile);
_finddata_t fileinfo;
_findfirst("D:\\Projects\\*.cpp", &fileinfo);
That will set all the file times to January 1, 1601 and you'll get an assert from _findfirst because _finddata_t uses __time64_t which has the minimum year of 1900.
Not sure what to do here or if this counts as a bug. Without the assert you'll get some garbage file time value (probably negative or something). Depending on your code you can try to use the Win32 API functions FindFirstFile/FindNextFile instead of _findfirst/_findnext since those functions will use FILETIME structures for time (same used by the system) which allows for dates going back to January 1, 1601.
kadabba
Thanks for the re-pro.
You're right about this. It does crash when it's not suppose to. I believe this is a bug that should be fixed. It doesn't say in the documentation that it's suppose to crash so either you have a situation here where something is wrong. After all none of us can assume anything about systems we have no control over. Therefore if crash is the only result of the API function then something is really wrong with it.
At the very least the API function should return -1.
So the obvious question is how to resolve this
Thanks.
-- Henrik
elainel311
Thanks for the suggestion.
So far I found that the handler rutine posted works fine in release mode but in debug mode an assertion is still given. I was under the impression that the invalid_parameter_handler would work in both cases
For now I re-implemented it with Win32 equivalent and removed any dependencies to the CRT. This naturally works fine.
Thanks.
-- Henrik
MukilanP
One solution is to use FindFirstFile/FindNextFile as I already stated.
Another one is to set the invalid parameter handler to a function that does nothing.
void
empty_invalid_parameter_handler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
}
int main()
{
....
_invalid_parameter_handler oldHandler;
oldHandler = _set_invalid_parameter_handler(empty_invalid_parameter_handler);
_finddata_t fileinfo;
_findfirst("E:\\Projects\\*.cpp", &fileinfo);
_set_invalid_parameter_handler(oldHandler);
}
This stops the program from crashing when a crt function receives an invalid parameter (that is what it really happens, some function that converts time value is very "aggresive" at validating its parameters and raises an invalid parameter error). With this invalid parameter handler set the program will continue and you will get -1 for the time values inf the _finddata_t structure.
Mark Marquis
The only way to reproduce this problem is to get the original files that caused the crash and run them through your debug build. But it is very likely that the cause of this is bad file data on their system which is something you can't anticipate.
As for the crash instruction, this doesn't mean anything much, since the problem could have occured before this instruction. But its possible that something is overwriting the esp or we have a stack overflow. But either way, the only possible solution is to have the original files and check the problem using the debug build.
One other thing I noticed when reading through the information on _fstat, if it gets information on a device then the time fields are not meaningful. Is it possible those files are device files
RMooreFL
You need to add this to stop the asserts
_CrtSetReportMode(_CRT_ASSERT, 0);