End Google Ads 201810 - BS.net 01 --> I have a windows client application that connects to a Linux daemon, both written in C++. One of the functions simply sends files from a particular directory on the Linux server back to the windows client app. The client app then unpacks the buffer and writes the files. This all works perfectly as long as none of the files on the server are larger than around 1mb. If files larger than this are packed the daemon crashes in the call to send the data. I've done a binary dump into a file prior to attempting to send the data (ie. prior to a crash) and all the files are packed in there perfectly

The code to pack the files on the Linux server is (with all error checking removed for clarity):

bool ClassName::PackSoftwareUpdateBuffer(char* baseDirectory, unsigned char* pBuffer)
{
int return_code;
char buf[1024];
dirent entry;
dirent *result;
struct stat st;
DIR* dir;
Directory *pDir = NULL;
Directory *pCurr = NULL;
Directory *pd = NULL;
Directory *pCurrDir = NULL;
int fd = 0;
size_t bytesread;

do
{
if(pCurrDir)
{
sprintf(buf, "%s/%s", baseDirectory, pCurrDir->DirectoryName);
dir = opendir(buf);

// Add a delimiter to the buffer so we know on the client
// we have a new directory
*pBuffer++ = '$';
strcpy((char*)pBuffer, pCurrDir->DirectoryName);
pBuffer += 199;
}
else
{
dir = opendir(baseDirectory);
}

for(return_code = readdir_r(dir, &entry, &result); result != NULL && return_code == 0; return_code = readdir_r(dir, &entry, &result))
{
// Add the path to the filename so we can 'stat' the file
if(pCurrDir)
sprintf(buf, "%s/%s/%s", baseDirectory, pCurrDir->DirectoryName, entry.d_name);
else
sprintf(buf, "%s/%s", baseDirectory, entry.d_name);

stat(buf, &st))

// Check if this is a directory
if(S_ISDIR(st.st_mode))
{
if(pCurrDir)
{
sprintf(buf, "%s/%s", pCurrDir->DirectoryName, entry.d_name);
pd = new Directory(buf);
}
else
pd = new Directory(entry.d_name);


if(pCurr)
pCurr = pCurr->pNext = pd;
else
pDir = pCurr = pd;

}
else
{
// Add the file data to the buffer
strcpy((char*)pBuffer, entry.d_name);
SET_BUFFER_UINT32(pBuffer, 50, st.st_size);

fd = open(buf, O_RDONLY);
pBuffer += 54;

read(fd, (void*)pBuffer, st.st_size);
close(fd);
pBuffer += st.st_size;
}
}

closedir(dir);

if(pCurrDir)
pCurrDir = pCurrDir->pNext;
else
pCurrDir = pDir;

if(!pCurrDir)
break;

}while(true);

DeleteDirectoryStructs(pDir);
return true;
}


Where a Directory is a struct declared/defined as:

// Directory information (used for software updates)
struct Directory
{
char DirectoryName[1024];
Directory *pNext;

Directory(char* dirName)
:pNext(NULL)
{
strcpy(DirectoryName, dirName);
}
};


The SET_BUFFER_UINT32 macro simply packs a numeric value into the buffer in network byte order. The pBuffer value passed into the function is a pointer to dynamically allocated memory. This is allocated in 1 mb chunks and always well and truly exceeds the amount of file data packed into the buffer (I have checked and re-checked this as it seemed the obvious reason for the issue). The crash occurs in the following function in the first call to send:


int ClassName::Write(unsigned char *buffer, unsigned int size)
{
int num = 0;
char *bufP = (char *)buffer;
unsigned int total = 0;

do
{
if((num = send(m_socket, (bufP + total), (size - total), 0))