mariadb/storage/connect/maputil.cpp
Mikhail Chalov 19af1890b5 Use memory safe snprintf() in Connect Engine
This commit replaces sprintf(buf, ...) with
snprintf(buf, sizeof(buf), ...),
specifically in the "easy" cases where buf is allocated with a size
known at compile time.

The changes make sure we are not write outside array/string bounds which
will lead to undefined behaviour. In case the code is trying to write
outside bounds - safe version of functions simply cut the string
messages so we process this gracefully.

All new code of the whole pull request, including one or several files
that are either new files or modified ones, are contributed under the BSD-new
license.  I am contributing on behalf of my employer Amazon Web Services,
Inc.

bsonudf.cpp warnings cleanup by Daniel Black

Reviewer: Daniel Black
2022-07-26 16:28:59 +10:00

200 lines
6.4 KiB
C++

#include "my_global.h"
#ifdef UNIX
#include "osutil.h"
#include <errno.h>
#include <stddef.h>
#else /* WINDOWS */
//#include <windows.h>
#include "osutil.h"
#endif /* WINDOWS */
#include <stdlib.h>
#include <stdio.h>
#include "global.h"
#include "plgdbsem.h"
#include "maputil.h"
#ifdef _WIN32
/***********************************************************************/
/* In Insert mode, just open the file for append. Otherwise */
/* create the mapping file object. The map handle can be released */
/* immediately because they will not be used anymore. */
/* If del is true in DELETE mode, then delete the whole file. */
/* Returns the file handle that can be used by caller. */
/***********************************************************************/
HANDLE CreateFileMap(PGLOBAL g, LPCSTR filename,
MEMMAP *mm, MODE mode, bool del)
{
HANDLE hFile;
HANDLE hFileMap;
DWORD access, share, disposition;
memset(mm, 0, sizeof(MEMMAP));
*g->Message = '\0';
switch (mode) {
case MODE_READ:
access = GENERIC_READ;
share = FILE_SHARE_READ;
disposition = OPEN_EXISTING;
break;
case MODE_UPDATE:
case MODE_DELETE:
access = GENERIC_READ | GENERIC_WRITE;
share = 0;
disposition = (del) ? TRUNCATE_EXISTING : OPEN_EXISTING;
break;
case MODE_INSERT:
access = GENERIC_WRITE;
share = 0;
disposition = OPEN_ALWAYS;
break;
default:
snprintf(g->Message, sizeof(g->Message), MSG(BAD_FUNC_MODE), "CreateFileMap", mode);
return INVALID_HANDLE_VALUE;
} // endswitch
hFile = CreateFile(filename, access, share, NULL, disposition,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
if (mode != MODE_INSERT) {
/*****************************************************************/
/* Create the file-mapping object. */
/*****************************************************************/
access = (mode == MODE_READ) ? PAGE_READONLY : PAGE_READWRITE;
hFileMap = CreateFileMapping(hFile, NULL, access, 0, 0, NULL);
if (!hFileMap) {
DWORD ler = GetLastError();
if (ler && ler != 1006) {
snprintf(g->Message, sizeof(g->Message), MSG(FILE_MAP_ERROR), filename, ler);
CloseHandle(hFile);
return INVALID_HANDLE_VALUE;
} else {
snprintf(g->Message, sizeof(g->Message), MSG(FILE_IS_EMPTY), filename);
return hFile;
} // endif ler
} // endif hFileMap
access = (mode == MODE_READ) ? FILE_MAP_READ : FILE_MAP_WRITE;
if (!(mm->memory = MapViewOfFile(hFileMap, access, 0, 0, 0))) {
DWORD ler = GetLastError();
snprintf(g->Message, sizeof(g->Message), "Error %ld in MapViewOfFile %s",
ler, filename);
CloseHandle(hFile);
return INVALID_HANDLE_VALUE;
} // endif memory
// lenH is the high-order word of the file size
mm->lenL = GetFileSize(hFile, &mm->lenH);
CloseHandle(hFileMap); // Not used anymore
} else // MODE_INSERT
/*****************************************************************/
/* The starting point must be the end of file as for append. */
/*****************************************************************/
SetFilePointer(hFile, 0, NULL, FILE_END);
return hFile;
} // end of CreateFileMap
bool CloseMemMap(LPVOID memory, size_t dwSize)
{
return (memory) ? !UnmapViewOfFile(memory) : false;
} // end of CloseMemMap
#else /* UNIX */
// Code to handle Linux and Solaris
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
/***********************************************************************/
/* In Insert mode, just open the file for append. Otherwise */
/* create the mapping file object. The map handle can be released */
/* immediately because they will not be used anymore. */
/* If del is true in DELETE mode, then delete the whole file. */
/* Returns the file handle that can be used by caller. */
/***********************************************************************/
HANDLE CreateFileMap(PGLOBAL g, LPCSTR fileName,
MEMMAP *mm, MODE mode, bool del)
{
unsigned int openMode;
int protmode;
HANDLE fd;
size_t filesize;
struct stat st;
memset(mm, 0, sizeof(MEMMAP));
*g->Message = '\0';
switch (mode) {
case MODE_READ:
openMode = O_RDONLY;
protmode = PROT_READ;
break;
case MODE_UPDATE:
case MODE_DELETE:
openMode = (del) ? (O_RDWR | O_TRUNC) : O_RDWR;
protmode = PROT_READ | PROT_WRITE;
break;
case MODE_INSERT:
openMode = (O_WRONLY | O_CREAT | O_APPEND);
protmode = PROT_WRITE;
break;
default:
snprintf(g->Message, sizeof(g->Message), MSG(BAD_FUNC_MODE), "CreateFileMap", mode);
return INVALID_HANDLE_VALUE;
} // endswitch
// Try to open the addressed file.
fd= global_open(g, MSGID_NONE, fileName, openMode);
if (fd != INVALID_HANDLE_VALUE && mode != MODE_INSERT) {
/* We must know about the size of the file. */
if (fstat(fd, &st)) {
snprintf(g->Message, sizeof(g->Message), MSG(FILE_MAP_ERROR), fileName, errno);
close(fd);
return INVALID_HANDLE_VALUE;
} // endif fstat
if ((filesize = st.st_size))
// Now we are ready to load the file. If mmap() is available we try
// this first. If not available or it failed we try to load it.
mm->memory = mmap(NULL, filesize, protmode, MAP_SHARED, fd, 0);
else
mm->memory = 0;
if (mm->memory != MAP_FAILED) {
mm->lenL = (mm->memory != 0) ? filesize : 0;
mm->lenH = 0;
} else {
strcpy(g->Message, "Memory mapping failed");
close(fd);
return INVALID_HANDLE_VALUE;
} // endif memory
} /* endif fd */
// mmap() call was successful. ??????????
return fd;
} // end of CreateFileMap
bool CloseMemMap(void *memory, size_t dwSize)
{
if (memory) {
// All this must be redesigned
int rc = msync((char*)memory, dwSize, MS_SYNC);
return (munmap((char*)memory, dwSize) < 0) ? true : false;
} else
return false;
} // end of CloseMemMap
#endif // UNIX