This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 8040f2a225 MINOR: [C++] Avoid multimap::find unspecified behavior
(#48607)
8040f2a225 is described below
commit 8040f2a22544876395529e02eb29d7a857dc7ffd
Author: Jordan Rupprecht <[email protected]>
AuthorDate: Tue Dec 23 00:01:26 2025 -0600
MINOR: [C++] Avoid multimap::find unspecified behavior (#48607)
### Rationale for this change
When a `std::multimap` has multiple entries with the same key, calling
`m.find(key)` returns an unspecified element.
Historically, this returns the first matching element. However, this is not
guaranteed, and recent libc++ changes make this return an arbitrary element.
This can lead to surprising behavior, i.e. different values returned based on
what other entries are in the multimap (and what the shape of the internal tree
is).
### What changes are included in this PR?
Replace `m.find(key)` with `m.equal_range(key)` to preserve behavior and
have predictable results. The behavior of this is guaranteed to return a range
of all matching elements in insertion order, and the beginning of the range is
the same element as what's normally returned by `m.find(key)`.
### Are these changes tested?
Yes
### Are there any user-facing changes?
No
Authored-by: Jordan Rupprecht <[email protected]>
Signed-off-by: David Li <[email protected]>
---
cpp/src/arrow/flight/transport/grpc/grpc_client.cc | 10 +++---
cpp/src/arrow/flight/transport/grpc/grpc_server.cc | 5 +--
.../arrow/flight/transport/grpc/util_internal.cc | 36 +++++++++-------------
3 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/cpp/src/arrow/flight/transport/grpc/grpc_client.cc
b/cpp/src/arrow/flight/transport/grpc/grpc_client.cc
index 6cf3242b07..a2af830db7 100644
--- a/cpp/src/arrow/flight/transport/grpc/grpc_client.cc
+++ b/cpp/src/arrow/flight/transport/grpc/grpc_client.cc
@@ -25,6 +25,7 @@
#include <sstream>
#include <string>
#include <thread>
+#include <tuple>
#include <unordered_map>
#include <utility>
@@ -448,10 +449,11 @@ arrow::Result<std::pair<std::string, std::string>>
GetBearerTokenHeader(
// Get the auth token if it exists, this can be in the initial or the
trailing metadata.
auto trailing_headers = context.GetServerTrailingMetadata();
auto initial_headers = context.GetServerInitialMetadata();
- auto bearer_iter = trailing_headers.find(internal::kAuthHeader);
- if (bearer_iter == trailing_headers.end()) {
- bearer_iter = initial_headers.find(internal::kAuthHeader);
- if (bearer_iter == initial_headers.end()) {
+ auto [bearer_iter, bearer_end] =
trailing_headers.equal_range(internal::kAuthHeader);
+ if (bearer_iter == bearer_end) {
+ std::tie(bearer_iter, bearer_end) =
+ initial_headers.equal_range(internal::kAuthHeader);
+ if (bearer_iter == bearer_end) {
return std::make_pair("", "");
}
}
diff --git a/cpp/src/arrow/flight/transport/grpc/grpc_server.cc
b/cpp/src/arrow/flight/transport/grpc/grpc_server.cc
index 3cc854b58f..03f22f8864 100644
--- a/cpp/src/arrow/flight/transport/grpc/grpc_server.cc
+++ b/cpp/src/arrow/flight/transport/grpc/grpc_server.cc
@@ -307,9 +307,10 @@ class GrpcServiceHandler final : public
FlightService::Service {
}
} else {
const auto client_metadata = context->client_metadata();
- const auto auth_header = client_metadata.find(kGrpcAuthHeader);
+ const auto [auth_header, auth_header_end] =
+ client_metadata.equal_range(kGrpcAuthHeader);
std::string token;
- if (auth_header == client_metadata.end()) {
+ if (auth_header == auth_header_end) {
token = "";
} else {
token = std::string(auth_header->second.data(),
auth_header->second.length());
diff --git a/cpp/src/arrow/flight/transport/grpc/util_internal.cc
b/cpp/src/arrow/flight/transport/grpc/util_internal.cc
index d29f1ce417..ff8607778b 100644
--- a/cpp/src/arrow/flight/transport/grpc/util_internal.cc
+++ b/cpp/src/arrow/flight/transport/grpc/util_internal.cc
@@ -55,31 +55,25 @@ static bool FromGrpcContext(const ::grpc::ClientContext&
ctx,
const std::multimap<::grpc::string_ref, ::grpc::string_ref>& trailers =
ctx.GetServerTrailingMetadata();
- const auto code_val = trailers.find(kGrpcStatusCodeHeader);
- if (code_val == trailers.end()) return false;
+ const auto [code_val_begin, code_val_end] =
trailers.equal_range(kGrpcStatusCodeHeader);
+ if (code_val_begin == code_val_end) return false;
- const auto message_val = trailers.find(kGrpcStatusMessageHeader);
- const std::optional<std::string> message =
- message_val == trailers.end()
- ? std::nullopt
- : std::optional<std::string>(
- std::string(message_val->second.data(),
message_val->second.size()));
+ std::optional<std::string> message;
+ if (const auto [it, end] = trailers.equal_range(kGrpcStatusMessageHeader);
it != end) {
+ message = std::string(it->second.data(), it->second.size());
+ }
- const auto detail_val = trailers.find(kGrpcStatusDetailHeader);
- const std::optional<std::string> detail_message =
- detail_val == trailers.end()
- ? std::nullopt
- : std::optional<std::string>(
- std::string(detail_val->second.data(),
detail_val->second.size()));
+ std::optional<std::string> detail_message;
+ if (const auto [it, end] = trailers.equal_range(kGrpcStatusDetailHeader); it
!= end) {
+ detail_message = std::string(it->second.data(), it->second.size());
+ }
- const auto grpc_detail_val = trailers.find(kBinaryErrorDetailsKey);
- const std::optional<std::string> detail_bin =
- grpc_detail_val == trailers.end()
- ? std::nullopt
- :
std::optional<std::string>(std::string(grpc_detail_val->second.data(),
-
grpc_detail_val->second.size()));
+ std::optional<std::string> detail_bin;
+ if (const auto [it, end] = trailers.equal_range(kBinaryErrorDetailsKey); it
!= end) {
+ detail_bin = std::string(it->second.data(), it->second.size());
+ }
- std::string code_str(code_val->second.data(), code_val->second.size());
+ std::string code_str(code_val_begin->second.data(),
code_val_begin->second.size());
*status = internal::ReconstructStatus(code_str, current_status,
std::move(message),
std::move(detail_message),
std::move(detail_bin),
std::move(flight_status_detail));