"Access violation writing location" with file.getline? (Only in release build) - c++

getting this error in an application written in C++ (VS 2010):
Unhandled exception at 0x77648da9 in divt.exe: 0xC0000005: Access
violation writing location 0x00000014.
it points to this function in free.c:
void __cdecl _free_base (void * pBlock)
{
int retval = 0;
if (pBlock == NULL)
return;
RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
retval = HeapFree(_crtheap, 0, pBlock);
if (retval == 0) //<-----------------------right here
{
errno = _get_errno_from_oserr(GetLastError());
}
}
Via debugging I was able to determine where its actually crashing:
void MenuState::LoadContentFromFile(char* File,std::string &Content)
{
std::string strbuf;
char buffer[1028];
std::fstream file;
file.open(File,std::ios_base::in);
if(file.fail())
{
Content = ErrorTable->GetString("W0001");
return;
}
if(file.is_open())
{
while(!file.eof())
{
file.getline(buffer,128,'\n'); // <----here
strbuf = buffer;
Content += strbuf + "\n";
}
}
file.close();
strbuf.clear();
}
It crashes on file.getline(buffer,128,'\n');
I don't understand why but it's only doing it in release build (Optimizations turned off), on debug build its working fine.
Any Ideas?

I know this is an old question, but when you encounter these sorts of issues buried deep in files such as, free.c or xmemory, you may also want to double check your project configuration. Especially when the issue pertains to only certain build configurations.
For example, in MSVC check your Project Properties > Configuration Properties > C/C++ > Code Generation > Runtime Library. Make sure it consistent for all dependencies and that it is set to a Debug/Release variant depending on the current build.

I would bet that the read prior to the read crashing the application actually failed (although I'm not quite sure why it would crash). The important thing to note is that eof() is only good for determining what caused a read failure (and typically suppressing an error message). In addition, you always want to check after the read whether it was successful. Finally, I can't see any reason why you don't read an std::string directly. In summary, try to use this loop instead:
for (std::string strbuf; std::getline(file, strbuf); ) {
Content += strbuf;
}

Asked a friend for help, we came up with this Solution:
std::string strbuf;
char buffer[256] = "\0";
FILE* f = fopen(File, "rt");
while(fgets(buffer,sizeof(buffer),f) != NULL)
{
Content += buffer;
}
fclose(f);
strbuf.clear();
Works fine, still thanks for your efforts.

Related

Libzip - Error: Error while opening the archive : no error

I'm trying to find out the solution to solve a problem;
In fact, i'm writing my own tool to make saves using libzip in C++ to compress the files.
Absolutly not finished but i wanted to make some tests, then i do and obtain a "funny" error from the log.
Here's my function:
void save(std::vector<std::string> filepath, std::string savepath){
int err;
savepath += time(NULL);
zip* saveArchive = zip_open(savepath.c_str(), ZIP_CREATE , &err);
if(err != ZIP_ER_OK) throw xif::sys_error("Error while opening the archive", zip_strerror(saveArchive));
for(int i = 0; i < filepath.size(); i++){
if(filepath[i].find("/") == std::string::npos){}
if(filepath[i].find(".cfg") == std::string::npos){
err = (int) zip_file_add(saveArchive, filepath[i].c_str(), NULL, NULL);
if(err == -1) throw xif::sys_error("Error while adding the files", zip_strerror(saveArchive));
}
}
if(zip_close(saveArchive) == -1) throw xif::sys_error("Error while closing the archive", zip_strerror(saveArchive));
}
I get a => Error : Error while opening the archive : No error
And, of course, i didn't have any .zip written.
If you could help me, thanks to you !
The documentation for zip_open says that it only sets *errorp if the open fails. Either test for saveArchive == nullptr or initialize err to
ZIP_ER_OK.
P.S. The search for '/' does nothing. Did you mean to put a continue in that block?
The other problematic line is:
savepath += time(NULL);
If that is the standard time function, that returns a time in seconds since the epoch. That will probably get truncated to a char, and then that char appended to the file name. That will cause strange characters to appear in the filename! I suggest using std::chrono to convert to text.

Time-of-Check, Time-of-Use issues involving access(), faccessat(), stat(), lstat(), fstat(), open(), and fopen()

I don't post here often, so bear with me while I try to decide how to solve this problem.
I'm updating a code base that hasn't been touched for between 10 - 20 years. The code was written without adherence to best practices, and by many authors with sometimes incomplete understandings of security conventions, or perhaps even before those conventions were common practice. The compiler used on this code is c++98 or c++03, but not more recent. The code is also cross platform between Linux and Windows.
All of that said, I need the help of some C++ veterans understanding the proper use of access(), stat() and open() and their perversions as it relates to TOCTOU issues.
Here is an example block of code illustrating the TOCTOU issue:
#ifdef WIN32
struct _stat buf;
#else
struct stat buf;
#endif //WIN32
FILE *fp;
char data[2560];
// Make sure file exists and is readable
#ifdef WIN32
if (_access(file.c_str(), R_OK) == -1) {
#else
if (access(file.c_str(), R_OK) == -1) {
#endif //WIN32
/* This is a fix from a previous
Stack-based Buffer Overflow
issue. I tried to keep the original
code as close to possible while
dealing with the potential security
issue, as I can't be certain of how
my change might effect the system. */
std::string checkStr("File ");
checkStr += file.c_str();
checkStr += " Not Found or Not Readable";
if(checkStr.length() >= 2560)
throw checkStr.c_str();
char message[2560];
sprintf(message, "File '%s' Not Found or Not Readable", file.c_str());
//DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
throw message;
}
// Get the file status information
#ifdef WIN32
if (_stat(file.c_str(), &buf) != 0) {
#else
if (stat(file.c_str(), &buf) != 0) {
#endif //WIN32
/* Same story here. */
std::string checkStr("File ");
checkStr += file.c_str();
checkStr += " No Status Available";
if(checkStr.length() >= 2560)
throw checkStr.c_str();
char message[2560];
sprintf(message, "File '%s' No Status Available", file.c_str());
//DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
throw message;
}
// Open the file for reading
fp = fopen(file.c_str(), "r");
if (fp == NULL) {
char message[2560];
sprintf(message, "File '%s' Cound Not be Opened", file.c_str());
//DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
throw message;
}
// Read the file
MvString s, ss;
while (fgets(data, sizeof(data), fp) != (char *)0) {
s = data;
s.trimBoth();
if (s.compare( 0, 5, "GROUP" ) == 0) {
//size_t t = s.find_last_of( ":" );
size_t t = s.find( ":" );
if (t != string::npos) {
ss = s.substr( t+1 ).c_str();
ss.trimBoth();
ss = ss.substr( 1, ss.length() - 3 ).c_str();
group_list.push_back( ss );
}
}
}
// Close the file
fclose(fp);
}
As you can see, the previous developer(s) wanted to make sure the user had access to "file", stat-ed "file", and then opened it without re-access()-ing and without re-stat()-ing "file" after fopen()-ing it. I understand why this is a TOCTOU problem, but I'm not sure of how to fix it.
From what I've researched, open() is preferred over fopen() and fstat() over stat(), but where does lstat() fit in? and if I do a stat, do I even need access() or faccessat()?
And to compound that, this needs to be compatable with a Windows compiler, and I've found articles saying that fopen() is better because it is cross platform while open() is not, making open() potentially unusable; this also seems to be the same for variations of stat() and access(), but I'm not certain.
If you've gotten this far, thank you for reading it all, and I welcome any criticism about the post and help.

Load the output of another command line program into mine

Ok suppose I have a program ( in windows a .exe file ) and when I run it, it outputs some information... now I'm writing another program ( in c++ ) and I need it to automatically run that .exe file and read the output so that it can process that information for further actions...
what should I do ?
Use popen or on windows (per comment) _popen. Basically it functions as the thing behind the | in some program | thing.
Normally I'm against posting complete code but I literally wrote this today and have it on hand, so, here you go. From what I understand C++ doesn't have a great interface that replaces popen but if you're bringing in the boost libraries or something at that layer there are solutions.
Note I use char[10] because in my application I know the output will be that short.
PopenWrapper(const std::string& command) {
fd = popen(command.c_str(), "r");
if(fd == NULL) {
throw PopenException("Failed to open command: " + command);
}
}
std::string get() {
char line[10];
fgets(line, sizeof(line), fd);
return std::string(line);
}
~PopenWrapper() {
if(fd != NULL) {
pclose(fd);
}
}

how to skip a directory while reading using dirent.h

i am trying to recursively open files using the functionality provided in dirent.h
My problem is:
i could not make it to skip directories which failed to open. I want it to open the directories which it can and skip those which it can't and move to the next directory instead of exiting with failure.
What should i do to fix this?
Here is a simple code i tried to use
int acessdirs(const char *path)
{
struct dirent *entry;
DIR *dp;
char fpath[300];
if(dp=opendir(path))
{
while((entry=readdir(dp)))
do things here
}
else
{
std::cout<<"error opening directory";
return 0;
}
return 1;
}
I used this same style on windows 7 and it works fine.But it crashed on windows xp and when i debugged it i found that it crashes while trying to open "system volume information".
I really dont need to access this folder and i was hoping if there is any way to skip it.
Here is my real code:
It is a little bit long.
int listdir(const char *path)
{
struct dirent *entry;
DIR *dp;
if(dp = opendir(path))
{
struct stat buf ;
while((entry = readdir(dp)))
{
std::string p(path);
p += "\\";
p += entry->d_name;
char fpath[300];
if(!stat(p.c_str(), &buf))
{
if(S_ISREG(buf.st_mode))
{
sprintf(fpath,"%s\\%s",path,entry->d_name);
stat(fpath, &buf);
std::cout<<"\n Size of \t"<<fpath<<"\t"<<buf.st_size;
fmd5=MDFile (fpath);
}//inner second if
if(S_ISDIR(buf.st_mode) &&
// the following is to ensure we do not dive into directories "." and ".."
strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..") )
{
listdir(p.c_str());
}
}//inner first if
else
std::cout << "ERROR in stat\n";
}//end while
closedir(dp);
}//first if
else
{
std::cout << "ERROR in opendir\n";
return 0;
}
return 1;
}//listdir()
Your biggest problem seems to be here:
sprintf(fpath,"%s\\%s",path,entry->d_name);
stat(fpath, &buf);
Without seeing fpath's declatation, it's tough to tell for certain, but you're either
Overflowing fpath in the sprintf call, leading to undefined behavior. "System Volume Information" is a long name. You should really use snprintf.
Not checking the return value of the stat call. If it returns -1, I'n not sure what the contents of buf will be.
More importantly, if you can use POSIX stuff, the function ftw is standard, and should provide most of the functionality you're trying to implement here.

Unable to capture standard output of process using Boost.Process

Currently am using Boost.Process from the Boost sandbox, and am having issues getting it to capture my standard output properly; wondering if someone can give me a second pair of eyeballs into what I might be doing wrong.
I'm trying to take thumbnails out of RAW camera images using DCRAW (latest version), and capture them for conversion to QT QImage's.
The process launch function:
namespace bf = ::boost::filesystem;
namespace bp = ::boost::process;
QImage DCRawInterface::convertRawImage(string path) {
// commandline: dcraw -e -c <srcfile> -> piped to stdout.
if ( bf::exists( path ) ) {
std::string exec = "bin\\dcraw.exe";
std::vector<std::string> args;
args.push_back("-v");
args.push_back("-c");
args.push_back("-e");
args.push_back(path);
bp::context ctx;
ctx.stdout_behavior = bp::capture_stream();
bp::child c = bp::launch(exec, args, ctx);
bp::pistream &is = c.get_stdout();
ofstream output("C:\\temp\\testcfk.jpg");
streamcopy(is, output);
}
return (NULL);
}
inline void streamcopy(std::istream& input, std::ostream& out) {
char buffer[4096];
int i = 0;
while (!input.eof() ) {
memset(buffer, 0, sizeof(buffer));
int bytes = input.readsome(buffer, sizeof buffer);
out.write(buffer, bytes);
i++;
}
}
Invoking the converter:
DCRawInterface DcRaw;
DcRaw.convertRawImage("test/CFK_2439.NEF");
The goal is to simply verify that I can copy the input stream to an output file.
Currently, if I comment out the following line:
args.push_back("-c");
then the thumbnail is written by DCRAW to the source directory with a name of CFK_2439.thumb.jpg, which proves to me that the process is getting invoked with the right arguments. What's not happening is connecting to the output pipe properly.
FWIW: I'm performing this test on Windows XP under Eclipse 3.5/Latest MingW (GCC 4.4).
[UPDATE]
From debugging, it would appear that by the time the code reaches streamcopy, the file/pipe is already closed - bytes = input.readsome(...) is never any value other than 0.
Well I think that you need to redirect correctly the output stream. In my application something like this works :
[...]
bp::command_line cl(_commandLine);
bp::launcher l;
l.set_stdout_behavior(bp::redirect_stream);
l.set_stdin_behavior(bp::redirect_stream);
l.set_merge_out_err(true);
bp::child c = l.start(cl);
bp::pistream& is = c.get_stdout();
string result;
string line;
while (std::getline(is, line) && !_isStopped)
{
result += line;
}
c.wait();
[...]
Without the redirect the stdout will go nowhere if I remember correctly. It is a good practice to wait for the process end if you want to get the whole output.
EDIT:
I'm on Linux with perhaps an old version of boost.process. i realize that your code is similar to the snippet I gave you. The c.wait() might be the key ...
EDIT: Boost.process 0.1 :-)
If migrating to the "latest" boost.process isn't an issue (as you sure know, there are several variants for this library) ,you could use the following (http://www.highscore.de/boost/process0.5/)
file_descriptor_sink sink("stdout.txt");
execute(
run_exe("test.exe"),
bind_stdout(sink)
);