malloc and snprintf bus core dump - c++

Function which worked previously, suddenly refuses cooperation. More precisely this snippet:
//If not, add to UIDS
printf("line 78\n");
free(s2);
printf("line 82\n");
char * ss = malloc(snprintf(NULL, 0, "%s:%d", myUIDs, userId) + 1);
printf("line 84\n");
sprintf(ss, "%s:%d", myUIDs, userId);
free(myUIDs);
myUIDs=ss;
free(buffer);
Program fails one line after "line 82" (no longer line 82, but it's only a debugging stop) with Segmentation Fault (core dumped).
If I change
char * ss = malloc(snprintf(NULL, 0, "%s:%d", myUIDs, userId) + 1); to
char * ss = malloc(snprintf(NULL, 0, "%s:%d", "", 1) + 1);
I get Bus Error: Code dumped instead. I'm working on this program for quite a long time, and I have a feeling it's something obvious, that I'm constantly overlooking because of exhaustion, but no programmer friends to ask for help at this time.
Whole function for context:
char* myUIDs; //string containing all UID-s, separated by colon
void printProcessInformation(char pid[],int isSetP, int isSetN, int isSetU){
//find full path name to your "stat" file
//DIR *dir;
//struct dirent *ent;
//Creating string with /proc/PID
char * s = malloc(snprintf(NULL, 0, "%s%s", "/proc/", pid) + 1);
sprintf(s, "%s%s", "/proc/", pid);
//Creating string with /proc/PID/psinfo (full path)
char * fullPath = malloc(snprintf(NULL, 0, "%s%s", s, "/psinfo") + 1);
sprintf(fullPath, "%s%s", s, "/psinfo");
free(s);
//printf("%s\n",fullPath);
//Reading data from file
FILE* file = fopen(fullPath, "r");
printf("line 37\n");
char* buffer;
buffer = (char*) malloc(sizeof(psinfo_t));
printf("line 40\n");
if(file == NULL)
{
//perror("Error: Couldn't open file");
return;
}
fread((void *)buffer, sizeof(psinfo_t), 1, file);
psinfo_t* pData = (psinfo_t*) buffer;
time_t sTime=pData->pr_start.tv_sec;
int pr_pid=pData->pr_pid;
char* fname=pData->pr_fname;
free(buffer);
buffer = (char*) malloc(sizeof(stat));
stat(fullPath,buffer);
struct stat* fileStat=(struct stat*) buffer;
fclose(file);
int userId=fileStat->st_uid;
struct passwd* pw=getpwuid(userId);
char* uid=pw->pw_name;
printf("line 58\n");
if(isSetU<0){
//Print results
printf("%8s", uid);
if(isSetP>0)
printf(" %5d",pr_pid);
printf(" %16s %.24s\n", fname, ctime(&sTime));
free(buffer);
}else{
//Or else, add UID to UIDS if it didn't appear before
//check if UID is in UIDS
printf("line 70\n");
char * s2 = malloc(snprintf(NULL, 0, "%s:%d", "", userId) + 1);
printf("line 72\n");
snprintf(s2, "%s:%d", "", userId);
if(strstr(myUIDs,s2)!=NULL){
free(s2);
free(buffer);
return;
}
//If not, add to UIDS
printf("line 78\n");
free(s2);
printf("line 82\n");
char * ss = malloc(snprintf(NULL, 0, "%s:%d", "", 1) + 1);
printf("line 84\n");
sprintf(ss, "%s:%d", myUIDs, userId);
free(myUIDs);
myUIDs=ss;
free(buffer);
}
}

There are several issues I see on further review...
In a nutshell, the error you are getting does not appear to be the result of the line you're executing, rather, a side effect of a previous corruption of memory.
Where do you initialize myUIDs? It looks like you could be accessing it when it has not been defined based on the code provided
You are assigning fname from pData which is a pointer to the dynamically allocated buffer... which you subsequently free on the next line of execution, which means that fname is now pointing to deallocated memory. Yet you attempt to read from it later in the code... which may well be leading you off on a random walk through memory.
There are multiple instances in the code where you are dynamically allocating memory, and then attempting to use it without ever validating that you actually got the allocation you requested.
You are calling malloc() based on the return value from snprintf() without ever validating that snprintf() returned you a non-negative value. Though, I doubt this is an issue, it's unwise.
To be sure, the symptoms you are describing are the result of the corruption of the heap. The question is where. I would strongly recommend the use of valgrind.
In addition, if it is available, have a look at asprintf() instead of the malloc( snprintf() ) work you are doing.

Related

Array isn't free'd after going out of scope

I have a simple char array used to read from a pipe.
This array is used in an infinite while cycle
int main()
{
mkfifo("process1_write", 0666);
mkfifo("process1_read", 0666);
int fd1,fd2;
fd1 = open(process1_write, O_RDWR);
fd2 = open(process1_read, O_RDONLY| O_NONBLOCK);
std::string outmsg = "{process: drv_rtnode_1, message: hi}";
while (1)
{
char str1[1050];
printf("cycle %d\n\t",i++);
int in = read(fd2, str1, 1024);
if(in>0)
{
printf("message: %s, in: %d\n", str1, in);
write(fd1, outmsg.c_str(), outmsg.size());
}
else
printf("No content received\n");
sleep(1);
}
return 0;
}
As you can see, str1 is instantiated on the stack as a local variable so I'd expect it to be free'd after each while-cycle.
However what I get is the following:
Cycle 1: receiving data from the PIPE, thus enterning if(in>0)
message: {"msg type": "status inst", "ProcessName": "process1", "StatusDetail": "dettaglio componente"}{"msg type": "status ses", "ProcessName": "process1", "GroupName": "MOT", "GroupSts": "Online", "ActiveSession": "PRI", "StatusDetail": "dettaglio sessione"}, in: 251
in = 251, so it's counting the number of characters correctly
Cycle 2: receiving LESS data from the PIPE
This time I'm receiving this message: {"state":"alive"}
But here's the printed output:
message: {"state":"alive"}tus inst", "ProcessName": "process1", "StatusDetail": "dettaglio componente"}{"msg type": "status ses", "ProcessName": "process1", "GroupName": "MOT", "GroupSts": "Online", "ActiveSession": "PRI", "StatusDetail": "dettaglio sessione"} , in: 17
in = 17, so the number of characters is, once again, correctly counted but my array has not been emptied at all
This happens no matter what kind of data I receive.
I also tried changing the code as follows:
char* str1 = new char[1050];
while (1)
{
printf("cycle %d\n\t",i++);
int in = read(fd2, str1, 1024);
if(in>0)
{
printf("message: %s, in: %d\n", str1, in);
write(fd1, outmsg.c_str(), outmsg.size());
}
else
printf("No content received\n");
sleep(1);
delete[] str1;
str1 = new char[1050];
}
But nothing has changed. It behaves exactly the same.
The following:
while (1)
{
char str1[1050];
allocates on the function call stack, but does it like this:
char str1[1050];
while (1)
{
So the location is reused, and only about 1050 bytes callocated.
The problem is, that for strings a nul terminator is needed:
int in = read(fd2, str1, 1024);
if (in > 0)
{
str1[in] = '\0';
Now the overwriting with shorter data does not show prior reads.

Can not "read" anything through the FUSE file system

I use fuse to build my own file system in MIT 6.824 lab, and the read operation is implemented in this function.
void
fuseserver_read(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi)
{
std::string buf;
int r;
if ((r = yfs->read(ino, size, off, buf)) == yfs_client::OK) {
char* retbuf = (char *)malloc(buf.size());
memcpy(retbuf,buf.data(),buf.size());
//Print the information of the result.
printf("debug read in fuse: the content of %lu is %s, size %lu\n",ino,retbuf, buf.size());
fuse_reply_buf(req,retbuf,buf.size());
} else {
fuse_reply_err(req, ENOENT);
}
//global definition
//struct fuse_lowlevel_ops fuseserver_oper;
//In main()
// fuseserver_oper.read = fuseserver_read;
I print the information of the buf before it return.
The write operation is also implemented, of course.
Then I run a simple test to read out some words.
//test.c
int main(){
//./yfs1 is the mount point of my filesystem
int fd = open("./yfs1/test-file",O_RDWR | O_CREAT,0777);
char* buf = "123";
char* readout;
readout = (char *)malloc(3);
int writesize = write(fd,buf,3);
int readsize = read(fd,readout,3);
printf("%s,%d\n",buf,writesize);
printf("%s,%d\n",readout,readsize);
close(fd);
}
I can get nothing by read(fd,readout,3), but the information printed by the fuseserver_read shows that the buffer is read out successfully before fuse_reply_buf
$ ./test
123,3
,0
debug read in fuse: the content of 2 is 123, size 3
So why the read() in test.c can not read anything from my file system??
Firstly, I've made a mistake to write my test file. The file pointer will point to the end of the file after "write" and of course can read nothing later. So simply reopen the file can make the test work.
Secondly, before read() operation of FUSE, the FUSE will getattr() first and truncate the result of the read() operation with the "size" attribute of the file. So it must be very careful to manipulate the attribute of a file.
There is also a need to notify that you have finished reading by sending an empty buffer, as an "EOF". You can do that by using reply_buf_limited.
Take a look at hello_ll example in the fuse source tree:
static void tfs_read(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi) {
(void) fi;
assert(ino == FILE_INO);
reply_buf_limited(req, file_contents, file_size, off, size);
}
static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
off_t off, size_t maxsize)
{
if (off < bufsize)
return fuse_reply_buf(req, buf + off,
min(bufsize - off, maxsize));
else
return fuse_reply_buf(req, NULL, 0);
}

I want to copy the data in (wchar_t *)buffer but i am unable to do so bcz there are other incompatible types,typecasting but not getting the result?

I want to print buffer data at one instance avoiding all other wprintf instances but unable to convert data in compatible type with buffer.
Have a look at code:
Kindly tell me how to get through it:
DWORD PrintEvent(EVT_HANDLE hEvent)
{
DWORD status = ERROR_SUCCESS;
PEVT_VARIANT pRenderedValues = NULL;
WCHAR wsGuid[50];
LPWSTR pwsSid = NULL;
//
// Beginning of functional Logic
//
for (;;)
{
if (!EvtRender(hContext, hEvent, EvtRenderEventValues, dwBufferSize, pRenderedValues, &dwBufferUsed, &dwPropertyCount))
{
if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
{
dwBufferSize = dwBufferUsed;
dwBytesToWrite = dwBufferSize;
pRenderedValues = (PEVT_VARIANT)malloc(dwBufferSize);
if (pRenderedValues)
{
EvtRender(hContext, hEvent, EvtRenderEventValues, dwBufferSize, pRenderedValues, &dwBufferUsed, &dwPropertyCount);
}
else
{
printf("malloc failed\n");
status = ERROR_OUTOFMEMORY;
break;
}
}
}
Buffer = (wchar_t*) malloc (1*wcslen(pRenderedValues[EvtSystemProviderName].StringVal));
//
// Print the values from the System section of the element.
wcscpy(Buffer,pRenderedValues[EvtSystemProviderName].StringVal);
int i = wcslen(Buffer);
if (NULL != pRenderedValues[EvtSystemProviderGuid].GuidVal)
{
StringFromGUID2(*(pRenderedValues[EvtSystemProviderGuid].GuidVal), wsGuid, sizeof(wsGuid)/sizeof(WCHAR));
wcscpy(Buffer+i,(wchar_t*)pRenderedValues[EvtSystemProviderGuid].GuidVal);
wprintf(L"Provider Guid: %s\n", wsGuid);
}
//Getting "??????" on screen after inclusion of guidval tell me the correct way to copy it??
wprintf(L"Buffer = %ls",Buffer);
//Also tell the way to copy unsigned values into buffer
wprintf(L"EventID: %lu\n", EventID);
wprintf(L"Version: %u\n", pRenderedValues[EvtSystemVersion].ByteVal);
wprintf(L"Level: %u\n", pRenderedValues[EvtSystemLevel].ByteVal);
wprintf(L"EventRecordID: %I64u\n", pRenderedValues[EvtSystemEventRecordId].UInt64Val);
if (EvtVarTypeNull != pRenderedValues[EvtSystemActivityID].Type)
{
StringFromGUID2(*(pRenderedValues[EvtSystemActivityID].GuidVal), wsGuid, sizeof(wsGuid)/sizeof(WCHAR));
wprintf(L"Correlation ActivityID: %s\n", wsGuid);
}
if (EvtVarTypeNull != pRenderedValues[EvtSystemRelatedActivityID].Type)
{
StringFromGUID2(*(pRenderedValues[EvtSystemRelatedActivityID].GuidVal), wsGuid, sizeof(wsGuid)/sizeof(WCHAR));
wprintf(L"Correlation RelatedActivityID: %s\n", wsGuid);
}
wprintf(L"Execution ProcessID: %lu\n", pRenderedValues[EvtSystemProcessID].UInt32Val);
wprintf(L"Execution ThreadID: %lu\n", pRenderedValues[EvtSystemThreadID].UInt32Val);
wprintf(L"Channel: %s\n",pRenderedValues[EvtSystemChannel].StringVal);
wprintf(L"Computer: %s\n", pRenderedValues[EvtSystemComputer].StringVal);
//
// Final Break Point
//
break;
}
}
The first error is when starting to write to the buffer:
Buffer = (wchar_t*) malloc (1*wcslen(pRenderedValues[EvtSystemProviderName].StringVal));
wcscpy(Buffer,pRenderedValues[EvtSystemProviderName].StringVal);
StringVal points to a wide character string with a trailing null byte, so you should
Buffer = malloc (sizeof(wchar_t)*(wcslen(pRenderedValues[EvtSystemProviderName].StringVal)+1));
or even better
Buffer = wcsdup(pRenderedValues[EvtSystemProviderName].StringVal);
Second error is when appending the GUID.
You are not allocating enough memory, you are just appending to the already full Buffer. And you are appending the raw GUID, not the GUID string. You should replace
int i = wcslen(Buffer);
wcscpy(Buffer+i,(wchar_t*)pRenderedValues[EvtSystemProviderGuid].GuidVal);
with something like
// Attention: memory leak if realloc returns NULL! So better use a second variable for the return code and check that before assigning to Buffer.
Buffer = realloc(Buffer, wcslen(Buffer) + wcslen(wsGuid) + 1);
wcscat(Buffer,wsGuid);
Also:
Besides, you should do better error checking for EvtRender. And you should check dwPropertyCount before accessing pRenderedValues[i].
BTW, wprintf(L"Buffer = %s",Buffer); (with %s instead of %ls) is sufficient with wprintf.
And to your last question: if you want to append unsigned values to a buffer you can use wsprintf to write to a string. If you can do it C++-only then you should consider using std::wstring. This is much easier for you with regard to allocating the buffers the right size.

Wrong value of UID in stat() and wrong pr_pid in psinfo_t

My function reads process list from /proc, then read process psinfo file into proper sturcture, as well as data about this file, and prints it.
The problem is, some of the data in those structures is wrong. As usual, the moment when program partially works, is the most confusing. It reads all data correct, except for PID (pr_pid), which is always 0, and UID of a file, which is also always 0. Why? Is it possible for data to load partially correctly? That shouldn't be possible.. 0 would be possible if we were talking about PPID, but solaris documentation clearly states pr_pid is the PID.
Links which I thought would have answers, but I couldn't find one:
http://docs.oracle.com/cd/E19963-01/html/821-1473/proc-4.html
http://linux.die.net/man/3/getpwnam
http://linux.die.net/man/2/stat
code:
void printProcessInformation(char pid[]){
//find full path name to your "stat" file
//DIR *dir;
//struct dirent *ent;
//Creating string with /proc/PID
char * s = malloc(snprintf(NULL, 0, "%s%s", "/proc/", pid) + 1);
sprintf(s, "%s%s", "/proc/", pid);
//Creating string with /proc/PID/psinfo (full path)
char * fullPath = malloc(snprintf(NULL, 0, "%s%s", s, "/psinfo") + 1);
sprintf(fullPath, "%s%s", s, "/psinfo");
free(s);
//printf("%s\n",fullPath);
//Reading data from file
FILE* file = fopen(fullPath, "r");
char* buffer;
buffer = (char*) malloc(sizeof(psinfo_t));
if(file == NULL)
{
perror("Error: Couldn't open file");
return;
}
fread((void *)buffer, sizeof(psinfo_t), 1, file);
psinfo_t* pData = (psinfo_t*) buffer;
free(buffer);
buffer = (char*) malloc(sizeof(stat));
stat(file,buffer);
struct stat* fileStat=(struct stat*) buffer;
printf("File owner id:%d\n",fileStat->st_uid);
free(buffer);
fclose(file);
struct passwd* pw=getpwuid(fileStat->st_uid);
//Loading data from structures
time_t sTime=pData->pr_start.tv_sec;
int pr_pid=pData->pr_pid;
char* fname=pData->pr_fname;
char* uid=pw->pw_name;
printf("%8s %5d %16s %.24s\n", uid, pr_pid, fname, ctime(&sTime));
}
Look at this:
psinfo_t* pData = (psinfo_t*) buffer;
free(buffer);
...
int pr_pid=pData->pr_pid;
You're setting pData to the contents of buffer in the first line and then freeing it. What pData points to is now lost to you, it may in fact be reused in the next malloc. When you try to use it in the last line above you're reading who knows what. You're freeing too agressively in this case. Don't free pData, (indirectly through buffer) until you're done using it.

C++ fwrite doesn't write to text file, have no idea why?

I have this code that basically reads from file and creates new file and write the content from the source to the destination file. It reads the buffer and creates the file, but fwrite
doesn't write the content to the newly created file, I have no idea why.
here is the code. (I have to use only this with _sopen, its part of legacy code)
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <share.h>
#include <sys\stat.h>
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
FILE* pfFile;
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
pfFile = fdopen(iFileId, "r");
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
// buffer = (char*) malloc (sizeof(char)*lSize);
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL)
{
return false;
}
// copy the file into the buffer:
result = fread (buffer,lSize,1,pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile );
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
return 0;
}
You can make main file and try it see if its working for you .
Thanks
Change your code to the following and then report your results:
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
{
FILE* pfFile;
if ((pfFile = fdopen(iFileId, "r")) != (FILE *)NULL)
{
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
if ((buffer = (char*) malloc (lSize)) == NULL)
return false;
// copy the file into the buffer:
result = fread (buffer,(size_t)lSize,1,pfFile);
fclose(pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
{
if ((pDesfFile = fdopen(iFileId2, "w+")) != (FILE *)NULL)
{
size_t f = fwrite (buffer, (size_t)lSize, 1, pDesfFile);
printf ("elements written <%d>\n", f);
if (f == 0)
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
}
}
}
}
return 0;
}
[edit]
for other posters, to show the usage/results of fwrite - what is the output of the following?
#include <stdio.h>
int main (int argc, char **argv) {
FILE *fp = fopen ("f.kdt", "w+");
printf ("wrote %d\n", fwrite ("asdf", 4, 1, fp));
fclose (fp);
}
[/edit]
sizeof(buffer) is the size of the pointer, i.e. 4 and not the number of items in the buffer
If buffer is an array then sizeof(buffer) would potentially work as it returns the number of bytes in the array.
The third parameter to fwrite is sizeof(buffer) which is 4 bytes (a pointer). You need to pass in the number of bytes to write instead (lSize).
Update: It also looks like you're missing the flag indicating the file should be Read/Write: _O_RDWR
This is working for me...
std::string szdes = "C:\\temp\\test_des.txt";
FILE* pDesfFile;
int iFileId2;
err = _sopen_s(&iFileId2, szdes.c_str(), _O_CREAT|_O_BINARY|_O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = _fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, lSize, pDesfFile );
fclose (pDesfFile);
Since I can't find info about _sopen, I can only look at man open. It reports:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Your call _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE); doesn't match either one of those, you seem to have flags and 'something' and modes / what is SH_DENY?
What is the result of man _sopen?
Finally, shouldn't you close the file descriptor from _sopen after you fclose the file pointer?
Your final lines should look like this, btw :
if (iFileId2 >= 0)
{
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile ); //<-- the f returns me 4
fclose (pDesfFile);
}
Since you currently write the file regardless of whether or not the fdopen after the O_CREAT succeeded. You also do the same thing at the top, you process the read (and the write) regardless of the success of the fdopen of the RDONLY file :(
You are using a mixture of C and C++. That is confusing.
The sizeof operator does not do what you expect it to do.
Looks like #PJL and #jschroedl found the real problem, but also in general:
Documentation for fwrite states:
fwrite returns the number of full items actually written, which may be less than count if an error occurs. Also, if an error occurs, the file-position indicator cannot be determined.
So if the return value is less than the count passed, use ferror to find out what happened.
The ferror routine (implemented both as a function and as a macro) tests for a reading or writing error on the file associated with stream. If an error has occurred, the error indicator for the stream remains set until the stream is closed or rewound, or until clearerr is called against it.