Skip to content

Commit 1891831

Browse files
committed
CXX-1116 result::insert_one needs to hold on to owned copy of _id ele
Fixes a bug where the return value of result::insert_one::inserted_id() could contain dangling references.
1 parent ed86f1e commit 1891831

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

src/mongocxx/result/insert_one.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,27 @@
1414

1515
#include <mongocxx/result/insert_one.hpp>
1616

17+
#include <bsoncxx/builder/stream/array.hpp>
18+
1719
#include <mongocxx/config/private/prelude.hh>
1820

1921
namespace mongocxx {
2022
MONGOCXX_INLINE_NAMESPACE_BEGIN
2123
namespace result {
2224

23-
insert_one::insert_one(result::bulk_write result, bsoncxx::types::value generated_id)
24-
: _result(std::move(result)), _generated_id(std::move(generated_id)) {
25+
insert_one::insert_one(result::bulk_write result, bsoncxx::types::value inserted_id)
26+
: _result(std::move(result)),
27+
_inserted_id_owned(bsoncxx::builder::stream::array{} << inserted_id
28+
<< bsoncxx::builder::stream::finalize),
29+
_inserted_id(_inserted_id_owned.view()[0].get_value()) {
2530
}
2631

2732
const result::bulk_write& insert_one::result() const {
2833
return _result;
2934
}
3035

3136
const bsoncxx::types::value& insert_one::inserted_id() const {
32-
return _generated_id;
37+
return _inserted_id;
3338
}
3439

3540
} // namespace result

src/mongocxx/result/insert_one.hpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#pragma once
1616

17+
#include <bsoncxx/array/value.hpp>
1718
#include <bsoncxx/types.hpp>
1819
#include <bsoncxx/types/value.hpp>
1920
#include <mongocxx/result/bulk_write.hpp>
@@ -28,7 +29,7 @@ namespace result {
2829
class MONGOCXX_API insert_one {
2930
public:
3031
// This constructor is public for testing purposes only
31-
insert_one(result::bulk_write result, bsoncxx::types::value generated_id);
32+
insert_one(result::bulk_write result, bsoncxx::types::value inserted_id);
3233

3334
///
3435
/// Returns the bulk write result for this insert operation.
@@ -40,13 +41,18 @@ class MONGOCXX_API insert_one {
4041
///
4142
/// Gets the _id of the inserted document.
4243
///
43-
/// @return The value of the _id field for inserted document.
44+
/// @return The value of the _id field for the inserted document.
4445
///
4546
const bsoncxx::types::value& inserted_id() const;
4647

4748
private:
4849
result::bulk_write _result;
49-
bsoncxx::types::value _generated_id;
50+
51+
// Array with a single element, containing the value of the _id field for the inserted document.
52+
bsoncxx::array::value _inserted_id_owned;
53+
54+
// Points into _inserted_id_owned.
55+
bsoncxx::types::value _inserted_id;
5056
};
5157

5258
} // namespace result

src/mongocxx/test/collection.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ TEST_CASE("CRUD functionality", "[driver::collection]") {
104104
REQUIRE(i == 1);
105105
}
106106

107+
SECTION("insert_one returns correct result object", "[collection]") {
108+
stdx::string_view expected_id{"foo"};
109+
110+
auto result = coll.insert_one(document{} << "_id" << expected_id << finalize);
111+
REQUIRE(result);
112+
REQUIRE(result->result().inserted_count() == 1);
113+
REQUIRE(result->inserted_id().type() == bsoncxx::type::k_utf8);
114+
REQUIRE(result->inserted_id().get_utf8().value == expected_id);
115+
}
116+
107117
SECTION("insert and read multiple documents", "[collection]") {
108118
document b1;
109119
document b2;

0 commit comments

Comments
 (0)