Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sharedMemory): x64 size error #2976 #4295

Merged
merged 8 commits into from
Nov 26, 2023
10 changes: 5 additions & 5 deletions Foundation/include/Poco/SharedMemory_WIN32.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ class Foundation_API SharedMemoryImpl: public RefCountedObject
SharedMemoryImpl& operator = (const SharedMemoryImpl&);

std::string _name;
HANDLE _memHandle;
HANDLE _fileHandle;
DWORD _size;
DWORD _mode;
char* _address;
HANDLE _memHandle;
HANDLE _fileHandle;
std::size_t _size;
DWORD _mode;
char* _address;
};


Expand Down
28 changes: 23 additions & 5 deletions Foundation/src/SharedMemory_WIN32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ SharedMemoryImpl::SharedMemoryImpl(const std::string& name, std::size_t size, Sh
_name(name),
_memHandle(INVALID_HANDLE_VALUE),
_fileHandle(INVALID_HANDLE_VALUE),
_size(static_cast<DWORD>(size)),
_size(size),
_mode(PAGE_READONLY),
_address(0)
{
Expand All @@ -37,22 +37,40 @@ SharedMemoryImpl::SharedMemoryImpl(const std::string& name, std::size_t size, Sh

std::wstring utf16name;
UnicodeConverter::toUTF16(_name, utf16name);
_memHandle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, _mode, 0, _size, utf16name.c_str());
#ifdef _WIN64
const DWORD dwMaxSizeLow = static_cast<DWORD>(_size & 0xFFFFFFFFULL);
const DWORD dwMaxSizeHigh = static_cast<DWORD>((_size & (0xFFFFFFFFULL << 32)) >> 32);
#else
if (_size > std::numeric_limits<DWORD>::max())
{
throw Poco::InvalidArgumentException(Poco::format("Requested shared memory size (%z) too large (max %lu)",
_size, std::numeric_limits<DWORD>::max()));
}
const DWORD dwMaxSizeLow = static_cast<DWORD>(_size);
const DWORD dwMaxSizeHigh = 0UL;
#endif
_memHandle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, _mode, dwMaxSizeHigh, dwMaxSizeLow, utf16name.c_str());

if (!_memHandle)
{
DWORD dwRetVal = GetLastError();
int retVal = static_cast<int>(dwRetVal);
#if defined (_WIN32_WCE)
throw SystemException(format("Cannot create shared memory object %s [Error %d: %s]", _name, static_cast<int>(dwRetVal), Error::getMessage(dwRetVal)));
throw SystemException(Poco::format("Cannot create shared memory object %s [Error %d: %s]",
_name, retVal, Error::getMessage(dwRetVal)));
#else
if (_mode != PAGE_READONLY || dwRetVal != 5)
throw SystemException(format("Cannot create shared memory object %s [Error %d: %s]", _name, static_cast<int>(dwRetVal), Error::getMessage(dwRetVal)));
{
throw SystemException(Poco::format("Cannot create shared memory object %s [Error %d: %s]",
_name, retVal, Error::getMessage(dwRetVal)), retVal);
}

_memHandle = OpenFileMappingW(PAGE_READONLY, FALSE, utf16name.c_str());
if (!_memHandle)
{
dwRetVal = GetLastError();
throw SystemException(format("Cannot open shared memory object %s [Error %d: %s]", _name, static_cast<int>(dwRetVal), Error::getMessage(dwRetVal)));
throw SystemException(Poco::format("Cannot open shared memory object %s [Error %d: %s]",
_name, retVal, Error::getMessage(dwRetVal)), retVal);
}
#endif
}
Expand Down
25 changes: 25 additions & 0 deletions Foundation/testsuite/src/SharedMemoryTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,30 @@ Poco::Path SharedMemoryTest::findDataFile(const std::string& afile)
}


void SharedMemoryTest::testCreateLarge()
{
#if POCO_OS == POCO_OS_WINDOWS_NT
try
{
#ifdef _WIN64
const size_t size = 0x03FFFFFFFFULL;
#else
const size_t size = 0xDFFFFFFFUL;
#endif
SharedMemory mem("hiLarge", size, SharedMemory::AM_WRITE);
assertTrue((mem.end() - mem.begin()) == size);
mem.begin()[0] = 'A';
mem.end()[-1] = 'Z';
}
catch (Poco::SystemException& ex)
{
// no memory, quite posible to happen
assertEqual(ERROR_NOT_ENOUGH_MEMORY, ex.code());
}
#endif
}


void SharedMemoryTest::setUp()
{
}
Expand All @@ -89,6 +113,7 @@ CppUnit::Test* SharedMemoryTest::suite()
#if !defined(POCO_NO_SHAREDMEMORY)
CppUnit_addTest(pSuite, SharedMemoryTest, testCreate);
CppUnit_addTest(pSuite, SharedMemoryTest, testCreateFromFile);
CppUnit_addTest(pSuite, SharedMemoryTest, testCreateLarge);
#endif
return pSuite;
}
1 change: 1 addition & 0 deletions Foundation/testsuite/src/SharedMemoryTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class SharedMemoryTest: public CppUnit::TestCase

void testCreate();
void testCreateFromFile();
void testCreateLarge();

void setUp();
void tearDown();
Expand Down
15 changes: 9 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,10 @@ NetSSL_OpenSSL-clean:
Data-libexec: Foundation-libexec
$(MAKE) -C $(POCO_BASE)/Data

Data-tests: Data-libexec cppunit
DataTest-libexec: Data-libexec
$(MAKE) -C $(POCO_BASE)/Data/testsuite/DataTest

Data-tests: Data-libexec DataTest-libexec cppunit
$(MAKE) -C $(POCO_BASE)/Data/testsuite

Data-samples: Data-libexec Data-libexec Data/SQLite-libexec Net-libexec
Expand All @@ -260,7 +263,7 @@ Data-clean:
Data/SQLite-libexec: Foundation-libexec Data-libexec
$(MAKE) -C $(POCO_BASE)/Data/SQLite

Data/SQLite-tests: Data/SQLite-libexec cppunit
Data/SQLite-tests: Data/SQLite-libexec DataTest-libexec cppunit
$(MAKE) -C $(POCO_BASE)/Data/SQLite/testsuite

Data/SQLite-clean:
Expand All @@ -270,7 +273,7 @@ Data/SQLite-clean:
Data/ODBC-libexec: Foundation-libexec Data-libexec
$(MAKE) -C $(POCO_BASE)/Data/ODBC

Data/ODBC-tests: Data/ODBC-libexec cppunit
Data/ODBC-tests: Data/ODBC-libexec DataTest-libexec cppunit
$(MAKE) -C $(POCO_BASE)/Data/ODBC/testsuite

Data/ODBC-clean:
Expand All @@ -280,7 +283,7 @@ Data/ODBC-clean:
Data/MySQL-libexec: Foundation-libexec Data-libexec
$(MAKE) -C $(POCO_BASE)/Data/MySQL

Data/MySQL-tests: Data/MySQL-libexec cppunit
Data/MySQL-tests: Data/MySQL-libexec DataTest-libexec cppunit
$(MAKE) -C $(POCO_BASE)/Data/MySQL/testsuite

Data/MySQL-clean:
Expand All @@ -290,7 +293,7 @@ Data/MySQL-clean:
Data/PostgreSQL-libexec: Foundation-libexec Data-libexec
$(MAKE) -C $(POCO_BASE)/Data/PostgreSQL

Data/PostgreSQL-tests: Data/PostgreSQL-libexec cppunit
Data/PostgreSQL-tests: Data/PostgreSQL-libexec DataTest-libexec cppunit
$(MAKE) -C $(POCO_BASE)/Data/PostgreSQL/testsuite

Data/PostgreSQL-clean:
Expand Down Expand Up @@ -407,7 +410,7 @@ Prometheus-libexec: Foundation-libexec Net-libexec
Prometheus-tests: Prometheus-libexec cppunit
$(MAKE) -C $(POCO_BASE)/Prometheus/testsuite

Prometheus-samples: Prometheus-libexec
Prometheus-samples: Prometheus-libexec Util-libexec
$(MAKE) -C $(POCO_BASE)/Prometheus/samples

Prometheus-clean:
Expand Down
2 changes: 1 addition & 1 deletion Net/include/Poco/Net/HTTPClientSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ class Net_API HTTPClientSession: public HTTPSession
HTTPBasicCredentials _proxyBasicCreds;
HTTPDigestCredentials _proxyDigestCreds;
HTTPNTLMCredentials _proxyNTLMCreds;
bool _ntlmProxyAuthenticated;
bool _ntlmProxyAuthenticated = false;

static ProxyConfig _globalProxyConfig;

Expand Down
3 changes: 3 additions & 0 deletions Net/include/Poco/Net/SocketAddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ class Net_API SocketAddress
/// Maximum length in bytes of a socket address.
};

static bool isUnixLocal(const std::string& hostAndPort);
/// Returns true iff `hostAndPort` is an absolute file path.

protected:
void init(const IPAddress& hostAddress, Poco::UInt16 portNumber);
void init(const std::string& hostAddress, Poco::UInt16 portNumber);
Expand Down
7 changes: 6 additions & 1 deletion Net/src/HTTPClientSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,12 @@ void HTTPClientSession::reconnect()
{
SocketAddress addr;
if (_proxyConfig.host.empty() || bypassProxy())
addr = SocketAddress(_host, _port);
{
if (SocketAddress::isUnixLocal(_host))
addr = SocketAddress(_host);
else
addr = SocketAddress(_host, _port);
}
else
addr = SocketAddress(_proxyConfig.host, _proxyConfig.port);

Expand Down
3 changes: 2 additions & 1 deletion Net/src/HTTPSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ void HTTPSession::connect(const SocketAddress& address)
_socket.connect(address, _connectionTimeout);
_socket.setReceiveTimeout(_receiveTimeout);
_socket.setSendTimeout(_sendTimeout);
_socket.setNoDelay(true);
if (address.family() != SocketAddress::UNIX_LOCAL)
_socket.setNoDelay(true);
// There may be leftover data from a previous (failed) request in the buffer,
// so we clear it.
_pCurrent = _pEnd = _pBuffer;
Expand Down
26 changes: 18 additions & 8 deletions Net/src/PollSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,11 @@
Poco::Timestamp start;
rc = epoll_wait(_epollfd, &_events[0],
static_cast<int>(_events.size()), static_cast<int>(remainingTime.totalMilliseconds()));
if (rc == 0) return result;
if (rc == 0)
{
if (keepWaiting(start, remainingTime)) continue;

Check warning

Code scanning / CodeQL

Continue statement that does not continue Warning

This 'continue' never re-runs the loop - the
loop condition
is always false.
return result;
}

// if we are hitting the events limit, resize it; even without resizing, the subseqent
// calls would round-robin through the remaining ready sockets, but it's better to give
Expand All @@ -187,13 +191,7 @@
// if interrupted and there's still time left, keep waiting
if (SocketImpl::lastError() == POCO_EINTR)
{
Poco::Timestamp end;
Poco::Timespan waited = end - start;
if (waited < remainingTime)
{
remainingTime -= waited;
continue;
}
if (keepWaiting(start, remainingTime)) continue;

Check warning

Code scanning / CodeQL

Continue statement that does not continue Warning

This 'continue' never re-runs the loop - the
loop condition
is always false.
}
else SocketImpl::error();
}
Expand Down Expand Up @@ -304,6 +302,18 @@
return epoll_ctl(_epollfd, op, fd, &ev);
}

static bool keepWaiting(const Poco::Timestamp& start, Poco::Timespan& remainingTime)
{
Poco::Timestamp end;
Poco::Timespan waited = end - start;
if (waited < remainingTime)
{
remainingTime -= waited;
return true;
}
return false;
}

#ifndef WEPOLL_H_
using EPollHandle = std::atomic<int>;
#else // WEPOLL_H_
Expand Down
29 changes: 16 additions & 13 deletions Net/src/SocketAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ SocketAddress::SocketAddress()

SocketAddress::SocketAddress(Family fam)
{
init(IPAddress(fam), 0);
init(IPAddress(fam), 0);
}


Expand Down Expand Up @@ -362,31 +362,34 @@ void SocketAddress::init(Family fam, const std::string& address)
}


bool SocketAddress::isUnixLocal(const std::string& hostAndPort)
{
#if defined(POCO_HAS_UNIX_SOCKET)
#if defined(POCO_OS_FAMILY_WINDOWS)
RegularExpression re(R"((?:[a-zA-Z]\:|\\\\[\w\s\.]+\\[\w\s\.$]+)\\(?:[\w\s\.]+\\)*[\w\s\.]*?$)");
if (re.match(hostAndPort)) return true;
#elif defined(POCO_OS_FAMILY_UNIX)
if (hostAndPort.size() && (hostAndPort[0] == '/')) return true;
#endif
#endif
return false;
}


void SocketAddress::init(const std::string& hostAndPort)
{
poco_assert (!hostAndPort.empty());

#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_HAS_UNIX_SOCKET)
RegularExpression re(R"((?:[a-zA-Z]\:|\\\\[\w\s\.]+\\[\w\s\.$]+)\\(?:[\w\s\.]+\\)*[\w\s\.]*?$)");
if (re.match(hostAndPort))
if (isUnixLocal(hostAndPort))
{
newLocal(hostAndPort);
return;
}
#endif

std::string host;
std::string port;
std::string::const_iterator it = hostAndPort.begin();
std::string::const_iterator end = hostAndPort.end();

#if defined(POCO_OS_FAMILY_UNIX)
if (*it == '/')
{
newLocal(hostAndPort);
return;
}
#endif
if (*it == '[')
{
++it;
Expand Down
3 changes: 2 additions & 1 deletion Net/testsuite/src/EchoServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ void EchoServer::run()
{
std::cerr << "EchoServer: " << exc.displayText() << std::endl;
}
ss.close();
}
}
_socket.close();
_done = true;
}

Expand All @@ -99,4 +101,3 @@ bool EchoServer::done()
{
return _done;
}

31 changes: 31 additions & 0 deletions Net/testsuite/src/HTTPClientSessionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/StreamCopier.h"
#include "Poco/File.h"
#include "Poco/Path.h"
#include "HTTPTestServer.h"
#include <istream>
#include <ostream>
Expand All @@ -26,6 +28,8 @@ using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPMessage;
using Poco::StreamCopier;
using Poco::File;
using Poco::Path;


HTTPClientSessionTest::HTTPClientSessionTest(const std::string& name): CppUnit::TestCase(name)
Expand Down Expand Up @@ -54,6 +58,32 @@ void HTTPClientSessionTest::testGetSmall()
}


void HTTPClientSessionTest::testGetSmallUnix()
{
#if defined(POCO_HAS_UNIX_SOCKET)
#if POCO_OS == POCO_OS_ANDROID
File socketFile("/data/local/tmp/SocketTest.sock");
#elif defined(POCO_OS_FAMILY_WINDOWS)
File socketFile(Path::tempHome() + "SocketTest.sock");
#else
File socketFile("/tmp/SocketTest.sock");
#endif // POCO_OS == POCO_OS_ANDROID
if (socketFile.exists()) socketFile.remove();
HTTPTestServer srv(socketFile.path());
HTTPClientSession s(socketFile.path());
HTTPRequest request(HTTPRequest::HTTP_GET, "/small");
s.sendRequest(request);
HTTPResponse response;
std::istream& rs = s.receiveResponse(response);
assertTrue(response.getContentLength() == HTTPTestServer::SMALL_BODY.length());
assertTrue(response.getContentType() == "text/plain");
std::ostringstream ostr;
StreamCopier::copyStream(rs, ostr);
assertTrue(ostr.str() == HTTPTestServer::SMALL_BODY);
#endif // POCO_HAS_UNIX_SOCKET
}


void HTTPClientSessionTest::testGetLarge()
{
HTTPTestServer srv;
Expand Down Expand Up @@ -373,6 +403,7 @@ CppUnit::Test* HTTPClientSessionTest::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPClientSessionTest");

CppUnit_addTest(pSuite, HTTPClientSessionTest, testGetSmall);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testGetSmallUnix);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testGetLarge);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testHead);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testPostSmallIdentity);
Expand Down
Loading
Loading