Skip to content

Commit d624313

Browse files
authored
Merge pull request #148 from WEBcodeX1/copilot/fix-d92a02bf-7a01-4798-ba73-5d7dcb491b51
Fix Map Access Exceptions Causing Server Crashes On Invalid Requests
2 parents 2d862c6 + 0511ca6 commit d624313

8 files changed

Lines changed: 118 additions & 37 deletions

File tree

src/ASProcessHandler.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,13 @@ void ASProcessHandler::forkProcessASHandler(ASProcessHandlerSHMPointer_t SHMAdre
6969

7070
for (const auto& Namespace: ConfigRef.Namespaces) {
7171

72-
for (const auto &Index:_VHostOffsetsPrecalc.at(Namespace.first)) {
72+
auto offsetIter = _VHostOffsetsPrecalc.find(Namespace.first);
73+
if (offsetIter == _VHostOffsetsPrecalc.end()) {
74+
ERR("_VHostOffsetsPrecalc does not contain Namespace:" << Namespace.first);
75+
continue;
76+
}
77+
78+
for (const auto &Index:offsetIter->second) {
7379

7480
pid_t ForkResult = fork();
7581

src/ASRequestHandler.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ void ASRequestHandler::_calculateOffsets() {
4141
}
4242

4343
for (const auto &Offset:_VHostOffsets) {
44-
uint16_t i = _VHostOffsets.at(Offset.first).OffsetStart;
45-
uint16_t n = _VHostOffsets.at(Offset.first).OffsetEnd;
44+
uint16_t i = Offset.second.OffsetStart;
45+
uint16_t n = Offset.second.OffsetEnd;
4646
while(i <= n) {
47-
_VHostOffsetsPrecalc.at(Offset.first).push_back(i);
47+
_VHostOffsetsPrecalc[Offset.first].push_back(i);
4848
++i;
4949
}
5050
}
@@ -72,7 +72,7 @@ void ASRequestHandler::addRequest(const ASRequestProps_t RequestProps) {
7272

7373
AppServerID_t ASRequestHandler::_getNextFreeAppServerID(string VirtualHost) {
7474
if (_VHostOffsetsPrecalc.contains(VirtualHost)) {
75-
for (const auto &Index:_VHostOffsetsPrecalc.at(VirtualHost)) {
75+
for (const auto &Index:_VHostOffsetsPrecalc[VirtualHost]) {
7676
DBG(180, "Namespace:" << VirtualHost << " Index:" << Index);
7777
if (!_Requests.contains(Index)) {
7878
DBG(140, "Requests do not contain Index, check SHM");

src/ClientHandler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ void ClientHandler::readClientData(const uint16_t FDCount)
121121
else {
122122
//- if filedescriptor exists in map, append buffer data
123123
if (Clients.contains(ReadFD)) {
124-
ClientRef_t ClientRef = Clients.at(ReadFD);
124+
ClientRef_t ClientRef = Clients[ReadFD];
125125
ClientRef->appendBuffer(Buffer, RcvBytes);
126126

127127
if (ClientRef->processRequests(SHMGetRequests, _ASRequestHandlerRef) > 0) {

src/Filesystem.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ void Filesystem::processFileProperties()
7070

7171
FindPos = FileName.rfind(".");
7272
string FileExtension = FileName.substr(FindPos+1, File.length()-FindPos);
73-
string MimeType = MimeRelations.at(FileExtension);
73+
74+
//- safely get mime type
75+
auto mimeIter = MimeRelations.find(FileExtension);
76+
string MimeType = (mimeIter != MimeRelations.end()) ? mimeIter->second : "application/octet-stream";
77+
7478
string ReplacePath = BasePath + Path + "/static";
7579
string RelPath = FilePath.substr(ReplacePath.length(), FilePath.length()-ReplacePath.length());
7680
string FileListKey = RelPath + "/" + FileName;
@@ -103,7 +107,13 @@ bool Filesystem::checkFileExists(const string &File)
103107

104108
FileProperties_t Filesystem::getFilePropertiesByFile(const string &File)
105109
{
106-
return _FilesExtended.at(File);
110+
auto iter = _FilesExtended.find(File);
111+
if (iter != _FilesExtended.end()) {
112+
return iter->second;
113+
}
114+
//- return empty FileProperties if not found (should not happen after checkFileExists)
115+
ERR("File not found in _FilesExtended map: " << File);
116+
return FileProperties_t{};
107117
}
108118

109119
string Filesystem::getFileEtag(const string &File) {

src/ResultOrder.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ void ResultOrder::append(
2323
)
2424
{
2525
if (_Requests.contains(ReqProps.ClientFD)) {
26-
_Requests.at(ReqProps.ClientFD).emplace(
26+
auto& clientRequests = _Requests[ReqProps.ClientFD];
27+
clientRequests.emplace(
2728
ReqNr, std::move(ReqProps)
2829
);
2930
}
@@ -57,34 +58,46 @@ void ResultOrder::processRequests(const HTTPType_t HTTPType)
5758

5859
//- HTTP/1.2 (unordered)
5960
if (HTTPType == HTTP1_2) {
60-
for (const auto& [ReqNr, ReqProps]: _Requests.at(ClientFD)) {
61-
if (ReqProps.HTTPVersion == HTTP1_2) {
62-
DBG(120, "HTTP1_2 RequestProps ClientFD:" << ReqProps.ClientFD << " HTTPType:" << ReqProps.HTTPVersion);
63-
ResultData.push_back(ReqProps);
61+
auto requestsIter = _Requests.find(ClientFD);
62+
if (requestsIter != _Requests.end()) {
63+
for (const auto& [ReqNr, ReqProps]: requestsIter->second) {
64+
if (ReqProps.HTTPVersion == HTTP1_2) {
65+
DBG(120, "HTTP1_2 RequestProps ClientFD:" << ReqProps.ClientFD << " HTTPType:" << ReqProps.HTTPVersion);
66+
ResultData.push_back(ReqProps);
67+
}
6468
}
6569
}
6670
}
6771

6872
//- HTTP/1.1 (ordered)
6973
if (HTTPType == HTTP1_1) {
7074

71-
RequestNr_t LastRequestNrCheck = _LastRequest.at(ClientFD).RequestNr;
75+
auto lastRequestIter = _LastRequest.find(ClientFD);
76+
if (lastRequestIter == _LastRequest.end()) {
77+
ERR("_LastRequest does not contain ClientFD:" << ClientFD);
78+
continue;
79+
}
80+
81+
RequestNr_t LastRequestNrCheck = lastRequestIter->second.RequestNr;
7282
RequestNr_t ReqIndex = 0;
7383

7484
DBG(200, "Processing HTTP1.1 LastReqNrCheck:" << LastRequestNrCheck);
7585

76-
for (const auto& [ReqNr, ReqProps]: _Requests.at(ClientFD)) {
86+
auto requestsIter = _Requests.find(ClientFD);
87+
if (requestsIter != _Requests.end()) {
88+
for (const auto& [ReqNr, ReqProps]: requestsIter->second) {
7789

78-
DBG(200, "ReqIndex:" << ReqIndex << " ReqNr:" << ReqNr);
90+
DBG(200, "ReqIndex:" << ReqIndex << " ReqNr:" << ReqNr);
7991

80-
//- if first ReqNr is not next (LastRequest+1) do not process
81-
if (ReqProps.HTTPVersion == HTTP1_1 && ReqIndex == 0 && ReqNr != LastRequestNrCheck) { break; }
82-
if (ReqProps.HTTPVersion == HTTP1_1 && ReqNr == LastRequestNrCheck) {
83-
DBG(200, "HTTP1_1 RequestProps ClientFD:" << ReqProps.ClientFD << " HTTPType:" << ReqProps.HTTPVersion);
84-
ResultData.push_back(ReqProps);
92+
//- if first ReqNr is not next (LastRequest+1) do not process
93+
if (ReqProps.HTTPVersion == HTTP1_1 && ReqIndex == 0 && ReqNr != LastRequestNrCheck) { break; }
94+
if (ReqProps.HTTPVersion == HTTP1_1 && ReqNr == LastRequestNrCheck) {
95+
DBG(200, "HTTP1_1 RequestProps ClientFD:" << ReqProps.ClientFD << " HTTPType:" << ReqProps.HTTPVersion);
96+
ResultData.push_back(ReqProps);
97+
}
98+
LastRequestNrCheck += 1;
99+
ReqIndex += 1;
85100
}
86-
LastRequestNrCheck += 1;
87-
ReqIndex += 1;
88101
}
89102
}
90103
}

src/ResultProcessor.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,13 @@ uint16_t ResultProcessor::_processPythonASResults()
206206
uint16_t processed = 0;
207207

208208
for (const auto& Namespace: ConfigRef.Namespaces) {
209-
for (const auto &Index: _VHostOffsetsPrecalc.at(Namespace.first)) {
209+
auto offsetIter = _VHostOffsetsPrecalc.find(Namespace.first);
210+
if (offsetIter == _VHostOffsetsPrecalc.end()) {
211+
ERR("_VHostOffsetsPrecalc does not contain Namespace:" << Namespace.first);
212+
continue;
213+
}
214+
215+
for (const auto &Index: offsetIter->second) {
210216
atomic_uint16_t* CanReadAddr = static_cast<atomic_uint16_t*>(getMetaAddress(Index, 0));
211217
atomic_uint16_t* WriteReadyAddr = static_cast<atomic_uint16_t*>(getMetaAddress(Index, 1));
212218
if (*(CanReadAddr) == 0 && *(WriteReadyAddr) == 1) {

src/ThreadHandler.cpp

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ void ThreadHandler::_addRequests(
2222

2323
for (const auto& RequestProps : Requests) {
2424
if (_RequestsSorted.contains(RequestProps.ClientFD)) {
25-
_RequestsSorted.at(RequestProps.ClientFD).push_back(std::move(RequestProps));
25+
_RequestsSorted[RequestProps.ClientFD].push_back(std::move(RequestProps));
2626
}
2727
else {
2828
ClientRequestDataVec_t ReqPropsVec;
@@ -45,11 +45,18 @@ void ThreadHandler::_checkProcessed()
4545
if (it->second->join()) {
4646
DBG(120, "Joined Thread for ClientFD:" << it->first << ", removing from Map");
4747

48-
_ProcessRequests.erase(
49-
_ProcessRequests.begin()+_ProcessRequestsIndex.at(it->first)
50-
);
48+
//- safely check if index exists before erasing
49+
auto indexIter = _ProcessRequestsIndex.find(it->first);
50+
if (indexIter != _ProcessRequestsIndex.end()) {
51+
_ProcessRequests.erase(
52+
_ProcessRequests.begin()+indexIter->second
53+
);
54+
_ProcessRequestsIndex.erase(indexIter);
55+
}
56+
else {
57+
ERR("_ProcessRequestsIndex does not contain ClientFD:" << it->first);
58+
}
5159

52-
_ProcessRequestsIndex.erase(it->first);
5360
_ClientThreads.erase(it++);
5461
}
5562
else {++it;};
@@ -138,11 +145,23 @@ void ClientThread::processRequests()
138145
RequestHeaderResult_t Headers;
139146
_parseRequestHeaders(_ClientRequests[i].HTTPPayload, Headers);
140147

141-
DBG(120, "RequestType:'" << BaseProps.at(2) << "'");
142-
DBG(120, "RequestPath:'" << BaseProps.at(1) << "'");
143-
DBG(120, "HTTPVersion:'" << BaseProps.at(0) << "'");
148+
//- validate BaseProps has minimum required elements
149+
if (BaseProps.size() < 3) {
150+
ERR("Invalid HTTP request - insufficient base properties");
151+
continue;
152+
}
153+
154+
DBG(120, "RequestType:'" << BaseProps[2] << "'");
155+
DBG(120, "RequestPath:'" << BaseProps[1] << "'");
156+
DBG(120, "HTTPVersion:'" << BaseProps[0] << "'");
144157

145-
const string NamespaceID = Headers.at("Host");
158+
//- check if Host header exists
159+
auto hostIter = Headers.find("Host");
160+
if (hostIter == Headers.end()) {
161+
ERR("Missing Host header in request");
162+
continue;
163+
}
164+
const string NamespaceID = hostIter->second;
146165
DBG(120, "NamespaceID:'" << NamespaceID << "'");
147166

148167
FileProperties_t FileProps;
@@ -158,13 +177,39 @@ void ClientThread::processRequests()
158177
}
159178
*/
160179

161-
NamespaceProps_t NamespaceProps = _Namespaces.at(NamespaceID);
180+
//- check if namespace exists
181+
auto namespaceIter = _Namespaces.find(NamespaceID);
182+
if (namespaceIter == _Namespaces.end()) {
183+
ERR("Namespace not found for NamespaceID:'" << NamespaceID << "'");
184+
185+
//- send 404 response for non-existent vhost
186+
stringstream current_date_404;
187+
std::time_t tt_404 = std::chrono::system_clock::to_time_t (std::chrono::system_clock::now());
188+
struct std::tm * ptm_404 = std::localtime(&tt_404);
189+
current_date_404 << std::put_time(ptm_404, "%a, %d %b %Y %T") << '\n';
190+
191+
string Response404 = "HTTP/1.1 404 Not Found\n";
192+
Response404.append("Date: ");
193+
Response404.append(current_date_404.str());
194+
Response404.append(" GMT\n");
195+
Response404.append("Server: falcon/0.1\n");
196+
Response404.append("Content-Length: 26\n");
197+
Response404.append("Content-Type: text/html\n\n");
198+
Response404.append("<html>404 Not Found</html>");
199+
200+
const char* send_buf_404 = Response404.c_str();
201+
const int rc_404 = write(_ClientRequests[i].ClientFDShared, send_buf_404, strlen(send_buf_404));
202+
if (rc_404 < 0) { ERR("write() err:" << strerror(errno)); }
203+
continue;
204+
}
205+
206+
NamespaceProps_t NamespaceProps = namespaceIter->second;
162207

163208
DBG(120, "NamespacePath:'" << NamespaceProps.FilesystemRef->Path << "'");
164209
DBG(120, "NamespaceBasePath:'" << NamespaceProps.FilesystemRef->BasePath << "'");
165210

166-
if (NamespaceProps.FilesystemRef->checkFileExists(BaseProps.at(1))) {
167-
FileProps = NamespaceProps.FilesystemRef->getFilePropertiesByFile(BaseProps.at(1));
211+
if (NamespaceProps.FilesystemRef->checkFileExists(BaseProps[1])) {
212+
FileProps = NamespaceProps.FilesystemRef->getFilePropertiesByFile(BaseProps[1]);
168213

169214
DBG(80, "ClientFileDescriptor:" << _ClientRequests[i].ClientFD);
170215
DBG(80, "FileDescriptor:" << FileProps.Filedescriptor);
@@ -174,7 +219,8 @@ void ClientThread::processRequests()
174219
DBG(80, "JSONConfig:" << NamespaceProps.JSONConfig);
175220

176221
//- if etags match, send 304 not-modified
177-
if (Headers.find("If-None-Match") != Headers.end() && Headers.at("If-None-Match") == FileProps.ETag) {
222+
auto etagIter = Headers.find("If-None-Match");
223+
if (etagIter != Headers.end() && etagIter->second == FileProps.ETag) {
178224
string Response304 = "HTTP/1.1 304 Not Modified\n";
179225
Response304.append("Date: ");
180226
Response304.append(current_date.str());
472 KB
Binary file not shown.

0 commit comments

Comments
 (0)