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

Validate mapping key uniqueness #1221

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions include/yaml-cpp/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const char* const INVALID_ANCHOR = "invalid anchor";
const char* const INVALID_ALIAS = "invalid alias";
const char* const INVALID_TAG = "invalid tag";
const char* const BAD_FILE = "bad file";
const char* const NON_UNIQUE_MAP_KEY = "map keys must be unique";

template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(
Expand Down Expand Up @@ -298,6 +299,16 @@ class YAML_CPP_API BadFile : public Exception {
BadFile(const BadFile&) = default;
~BadFile() YAML_CPP_NOEXCEPT override;
};

class YAML_CPP_API NonUniqueMapKey : public RepresentationException {
public:
template <typename Key>
NonUniqueMapKey(const Mark& mark_, const Key& key)
: RepresentationException(mark_, ErrorMsg::NON_UNIQUE_MAP_KEY) {}
NonUniqueMapKey(const NonUniqueMapKey&) = default;
~NonUniqueMapKey() YAML_CPP_NOEXCEPT override;
};

} // namespace YAML

#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
2 changes: 1 addition & 1 deletion include/yaml-cpp/node/detail/impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ inline void node_data::force_insert(const Key& key, const Value& value,

node& k = convert_to_node(key, pMemory);
node& v = convert_to_node(value, pMemory);
insert_map_pair(k, v);
insert_map_pair(k, v, true);
}

template <typename T>
Expand Down
2 changes: 1 addition & 1 deletion include/yaml-cpp/node/detail/node_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class YAML_CPP_API node_data {
void reset_sequence();
void reset_map();

void insert_map_pair(node& key, node& value);
void insert_map_pair(node& key, node& value, bool force = false);
void convert_to_map(const shared_memory_holder& pMemory);
void convert_sequence_to_map(const shared_memory_holder& pMemory);

Expand Down
1 change: 1 addition & 0 deletions src/exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ BadPushback::~BadPushback() YAML_CPP_NOEXCEPT = default;
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT = default;
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT = default;
BadFile::~BadFile() YAML_CPP_NOEXCEPT = default;
NonUniqueMapKey::~NonUniqueMapKey() YAML_CPP_NOEXCEPT = default;
} // namespace YAML
7 changes: 6 additions & 1 deletion src/node_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,12 @@ void node_data::reset_map() {
m_undefinedPairs.clear();
}

void node_data::insert_map_pair(node& key, node& value) {
void node_data::insert_map_pair(node& key, node& value, bool force) {
if (!force && !key.scalar().empty())
for (const auto& mapEntry : m_map)
if (mapEntry.first->scalar() == key.scalar())
throw NonUniqueMapKey(m_mark, key);

m_map.emplace_back(&key, &value);

if (!key.is_defined() || !value.is_defined())
Expand Down
4 changes: 4 additions & 0 deletions test/integration/load_node_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,5 +360,9 @@ TEST(LoadNodeTest, BlockCRNLEncoded) {
EXPECT_EQ(1, node["followup"].as<int>());
}

TEST(LoadNodeTest, NonUniqueMapKey) {
EXPECT_THROW(Load("{a: A, b: B, a: A}"), NonUniqueMapKey);
}

} // namespace
} // namespace YAML