Skip to content

Commit e01d0c3

Browse files
committed
Fix bugprone-unchecked-optional-access findings
Clang-tidy has the aforementioned check, which shows a few places in the core where we ignored the required optional checks. Fix all uses. Note, we cannot enable the check that this time because of some weird code in health.hpp that crashes tidy[1]. That will need to be a future improvement. There are tests that call something like ASSERT(optional) EXPECT(optional->foo()) While this isn't an actual violation, clang-tidy doesn't seem to be smart enough to deal with it, so add some explicit checks. [1] llvm/llvm-project#55530 Tested: Redfish service validator passes. Change-Id: Ied579cd0b957efc81aff5d5d1091a740a7a2d7e3 Signed-off-by: Ed Tanous <[email protected]>
1 parent 1ccf70f commit e01d0c3

File tree

12 files changed

+156
-106
lines changed

12 files changed

+156
-106
lines changed

http/http2_connection.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ class HTTP2Connection :
154154
completeResponseFields(thisReq, thisRes);
155155
thisRes.addHeader(boost::beast::http::field::date, getCachedDateStr());
156156

157-
boost::beast::http::fields& fields = thisRes.stringResponse->base();
158-
std::string code = std::to_string(thisRes.stringResponse->result_int());
157+
boost::beast::http::fields& fields = thisRes.stringResponse.base();
158+
std::string code = std::to_string(thisRes.stringResponse.result_int());
159159
hdr.emplace_back(headerFromStringViews(":status", code));
160160
for (const boost::beast::http::fields::value_type& header : fields)
161161
{

http/http_client.hpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct PendingRequest
125125
{}
126126
};
127127

128+
namespace http = boost::beast::http;
128129
class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo>
129130
{
130131
private:
@@ -137,10 +138,9 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo>
137138
uint32_t connId;
138139

139140
// Data buffers
140-
boost::beast::http::request<boost::beast::http::string_body> req;
141-
std::optional<
142-
boost::beast::http::response_parser<boost::beast::http::string_body>>
143-
parser;
141+
http::request<http::string_body> req;
142+
using parser_type = http::response_parser<http::string_body>;
143+
std::optional<parser_type> parser;
144144
boost::beast::flat_static_buffer<httpReadBufferSize> buffer;
145145
Response res;
146146

@@ -329,9 +329,10 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo>
329329
{
330330
state = ConnState::recvInProgress;
331331

332-
parser.emplace(std::piecewise_construct, std::make_tuple());
332+
parser_type& thisParser = parser.emplace(std::piecewise_construct,
333+
std::make_tuple());
333334

334-
parser->body_limit(connPolicy->requestByteLimit);
335+
thisParser.body_limit(connPolicy->requestByteLimit);
335336

336337
timer.expires_after(std::chrono::seconds(30));
337338
timer.async_wait(std::bind_front(onTimeout, weak_from_this()));
@@ -340,14 +341,14 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo>
340341
if (sslConn)
341342
{
342343
boost::beast::http::async_read(
343-
*sslConn, buffer, *parser,
344+
*sslConn, buffer, thisParser,
344345
std::bind_front(&ConnectionInfo::afterRead, this,
345346
shared_from_this()));
346347
}
347348
else
348349
{
349350
boost::beast::http::async_read(
350-
conn, buffer, *parser,
351+
conn, buffer, thisParser,
351352
std::bind_front(&ConnectionInfo::afterRead, this,
352353
shared_from_this()));
353354
}
@@ -375,6 +376,10 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo>
375376
}
376377
BMCWEB_LOG_DEBUG("recvMessage() bytes transferred: {}",
377378
bytesTransferred);
379+
if (!parser)
380+
{
381+
return;
382+
}
378383
BMCWEB_LOG_DEBUG("recvMessage() data: {}", parser->get().body());
379384

380385
unsigned int respCode = parser->get().result_int();

http/http_connection.hpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ class Connection :
9494
// don't require auth
9595
if (preverified)
9696
{
97+
if (!req)
98+
{
99+
return false;
100+
}
97101
mtlsSession = verifyMtlsUser(req->ipAddress, ctx);
98102
if (mtlsSession)
99103
{
@@ -202,6 +206,10 @@ class Connection :
202206
void handle()
203207
{
204208
std::error_code reqEc;
209+
if (!parser)
210+
{
211+
return;
212+
}
205213
crow::Request& thisReq = req.emplace(parser->release(), reqEc);
206214
if (reqEc)
207215
{
@@ -363,6 +371,10 @@ class Connection :
363371
{
364372
return;
365373
}
374+
if (!req)
375+
{
376+
return;
377+
}
366378
req->ipAddress = ip;
367379
}
368380

@@ -389,7 +401,10 @@ class Connection :
389401
void doReadHeaders()
390402
{
391403
BMCWEB_LOG_DEBUG("{} doReadHeaders", logPtr(this));
392-
404+
if (!parser)
405+
{
406+
return;
407+
}
393408
// Clean up any previous Connection.
394409
boost::beast::http::async_read_header(
395410
adaptor, buffer, *parser,
@@ -475,6 +490,10 @@ class Connection :
475490
void doRead()
476491
{
477492
BMCWEB_LOG_DEBUG("{} doRead", logPtr(this));
493+
if (!parser)
494+
{
495+
return;
496+
}
478497
startDeadline();
479498
boost::beast::http::async_read_some(
480499
adaptor, buffer, *parser,
@@ -515,7 +534,7 @@ class Connection :
515534
{
516535
BMCWEB_LOG_DEBUG("{} doWrite", logPtr(this));
517536
thisRes.preparePayload();
518-
serializer.emplace(*thisRes.stringResponse);
537+
serializer.emplace(thisRes.stringResponse);
519538
startDeadline();
520539
boost::beast::http::async_write(adaptor, *serializer,
521540
[this, self(shared_from_this())](

http/http_response.hpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,26 @@ struct Response
2323
using response_type =
2424
boost::beast::http::response<boost::beast::http::string_body>;
2525

26-
std::optional<response_type> stringResponse;
26+
response_type stringResponse;
2727

2828
nlohmann::json jsonValue;
2929

3030
void addHeader(std::string_view key, std::string_view value)
3131
{
32-
stringResponse->insert(key, value);
32+
stringResponse.insert(key, value);
3333
}
3434

3535
void addHeader(boost::beast::http::field key, std::string_view value)
3636
{
37-
stringResponse->insert(key, value);
37+
stringResponse.insert(key, value);
3838
}
3939

4040
void clearHeader(boost::beast::http::field key)
4141
{
42-
stringResponse->erase(key);
42+
stringResponse.erase(key);
4343
}
4444

45-
Response() : stringResponse(response_type{}) {}
45+
Response() = default;
4646

4747
Response(Response&& res) noexcept :
4848
stringResponse(std::move(res.stringResponse)),
@@ -73,7 +73,7 @@ struct Response
7373
return *this;
7474
}
7575
stringResponse = std::move(r.stringResponse);
76-
r.stringResponse.emplace(response_type{});
76+
r.stringResponse.clear();
7777
jsonValue = std::move(r.jsonValue);
7878

7979
// Only need to move completion handler if not already completed
@@ -98,27 +98,27 @@ struct Response
9898

9999
void result(unsigned v)
100100
{
101-
stringResponse->result(v);
101+
stringResponse.result(v);
102102
}
103103

104104
void result(boost::beast::http::status v)
105105
{
106-
stringResponse->result(v);
106+
stringResponse.result(v);
107107
}
108108

109109
boost::beast::http::status result() const
110110
{
111-
return stringResponse->result();
111+
return stringResponse.result();
112112
}
113113

114114
unsigned resultInt() const
115115
{
116-
return stringResponse->result_int();
116+
return stringResponse.result_int();
117117
}
118118

119119
std::string_view reason() const
120120
{
121-
return stringResponse->reason();
121+
return stringResponse.reason();
122122
}
123123

124124
bool isCompleted() const noexcept
@@ -128,29 +128,29 @@ struct Response
128128

129129
std::string& body()
130130
{
131-
return stringResponse->body();
131+
return stringResponse.body();
132132
}
133133

134134
std::string_view getHeaderValue(std::string_view key) const
135135
{
136-
return stringResponse->base()[key];
136+
return stringResponse.base()[key];
137137
}
138138

139139
void keepAlive(bool k)
140140
{
141-
stringResponse->keep_alive(k);
141+
stringResponse.keep_alive(k);
142142
}
143143

144144
bool keepAlive() const
145145
{
146-
return stringResponse->keep_alive();
146+
return stringResponse.keep_alive();
147147
}
148148

149149
void preparePayload()
150150
{
151151
// This code is a throw-free equivalent to
152152
// beast::http::message::prepare_payload
153-
boost::optional<uint64_t> pSize = stringResponse->payload_size();
153+
boost::optional<uint64_t> pSize = stringResponse.payload_size();
154154
using boost::beast::http::status;
155155
using boost::beast::http::status_class;
156156
using boost::beast::http::to_status_class;
@@ -160,12 +160,11 @@ struct Response
160160
}
161161
else
162162
{
163-
bool is1XXReturn = to_status_class(stringResponse->result()) ==
163+
bool is1XXReturn = to_status_class(stringResponse.result()) ==
164164
status_class::informational;
165165
if (*pSize > 0 &&
166-
(is1XXReturn ||
167-
stringResponse->result() == status::no_content ||
168-
stringResponse->result() == status::not_modified))
166+
(is1XXReturn || stringResponse.result() == status::no_content ||
167+
stringResponse.result() == status::not_modified))
169168
{
170169
BMCWEB_LOG_CRITICAL(
171170
"{} Response content provided but code was no-content or not_modified, which aren't allowed to have a body",
@@ -174,21 +173,22 @@ struct Response
174173
body().clear();
175174
}
176175
}
177-
stringResponse->content_length(*pSize);
176+
stringResponse.content_length(*pSize);
178177
}
179178

180179
void clear()
181180
{
182181
BMCWEB_LOG_DEBUG("{} Clearing response containers", logPtr(this));
183-
stringResponse.emplace(response_type{});
182+
stringResponse.clear();
183+
stringResponse.body().shrink_to_fit();
184184
jsonValue = nullptr;
185185
completed = false;
186186
expectedHash = std::nullopt;
187187
}
188188

189189
void write(std::string_view bodyPart)
190190
{
191-
stringResponse->body() += std::string(bodyPart);
191+
stringResponse.body() += std::string(bodyPart);
192192
}
193193

194194
std::string computeEtag() const

include/persistent_data.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,10 @@ class ConfigFile
234234
session["username"] = p.second->username;
235235
session["csrf_token"] = p.second->csrfToken;
236236
session["client_ip"] = p.second->clientIp;
237-
if (p.second->clientId)
237+
const std::optional<std::string>& clientId = p.second->clientId;
238+
if (clientId)
238239
{
239-
session["client_id"] = *p.second->clientId;
240+
session["client_id"] = *clientId;
240241
}
241242
sessions.emplace_back(std::move(session));
242243
}

redfish-core/include/query.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ inline bool handleIfMatch(crow::App& app, const crow::Request& req,
135135

136136
std::optional<query_param::Query> queryOpt =
137137
query_param::parseParameters(req.url().params(), asyncResp->res);
138-
if (queryOpt == std::nullopt)
138+
if (!queryOpt)
139139
{
140140
return false;
141141
}

redfish-core/include/utils/json_utils.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ bool readJsonPatch(const crow::Request& req, crow::Response& res,
552552
std::string_view key, UnpackTypes&&... in)
553553
{
554554
std::optional<nlohmann::json> jsonRequest = readJsonPatchHelper(req, res);
555-
if (jsonRequest == std::nullopt)
555+
if (!jsonRequest)
556556
{
557557
return false;
558558
}

redfish-core/lib/account_service.hpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,7 +1806,7 @@ inline void processAfterCreateUser(
18061806
inline void processAfterGetAllGroups(
18071807
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
18081808
const std::string& username, const std::string& password,
1809-
const std::optional<std::string>& roleId, std::optional<bool> enabled,
1809+
const std::string& roleId, bool enabled,
18101810
std::optional<std::vector<std::string>> accountTypes,
18111811
const std::vector<std::string>& allGroupsList)
18121812
{
@@ -1871,15 +1871,14 @@ inline void processAfterGetAllGroups(
18711871
messages::internalError(asyncResp->res);
18721872
return;
18731873
}
1874-
18751874
crow::connections::systemBus->async_method_call(
18761875
[asyncResp, username, password](const boost::system::error_code& ec2,
18771876
sdbusplus::message_t& m) {
18781877
processAfterCreateUser(asyncResp, username, password, ec2, m);
18791878
},
18801879
"xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
18811880
"xyz.openbmc_project.User.Manager", "CreateUser", username, userGroups,
1882-
*roleId, *enabled);
1881+
roleId, enabled);
18831882
}
18841883

18851884
inline void handleAccountCollectionPost(
@@ -1892,24 +1891,28 @@ inline void handleAccountCollectionPost(
18921891
}
18931892
std::string username;
18941893
std::string password;
1895-
std::optional<std::string> roleId("User");
1896-
std::optional<bool> enabled = true;
1894+
std::optional<std::string> roleIdJson;
1895+
std::optional<bool> enabledJson;
18971896
std::optional<std::vector<std::string>> accountTypes;
1898-
if (!json_util::readJsonPatch(
1899-
req, asyncResp->res, "UserName", username, "Password", password,
1900-
"RoleId", roleId, "Enabled", enabled, "AccountTypes", accountTypes))
1897+
if (!json_util::readJsonPatch(req, asyncResp->res, "UserName", username,
1898+
"Password", password, "RoleId", roleIdJson,
1899+
"Enabled", enabledJson, "AccountTypes",
1900+
accountTypes))
19011901
{
19021902
return;
19031903
}
19041904

1905-
std::string priv = getPrivilegeFromRoleId(*roleId);
1905+
std::string roleId = roleIdJson.value_or("User");
1906+
std::string priv = getPrivilegeFromRoleId(roleId);
19061907
if (priv.empty())
19071908
{
1908-
messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId");
1909+
messages::propertyValueNotInList(asyncResp->res, roleId, "RoleId");
19091910
return;
19101911
}
19111912
roleId = priv;
19121913

1914+
bool enabled = enabledJson.value_or(true);
1915+
19131916
// Reading AllGroups property
19141917
sdbusplus::asio::getProperty<std::vector<std::string>>(
19151918
*crow::connections::systemBus, "xyz.openbmc_project.User.Manager",

0 commit comments

Comments
 (0)