Fixes #9068: raise a ValueError when trying to set properties with empty names (#9085)

* Fixes #9068

* fix a problem with empty labels in s-group parsing

* fix empty column names in smiles suppliers

* add the check to setPODVal()

---------

Co-authored-by: = <=>
This commit is contained in:
Greg Landrum
2026-02-09 05:58:25 +01:00
committed by GitHub
parent c1b67f0c03
commit 3aab2653cd
8 changed files with 144 additions and 11 deletions

View File

@@ -1,5 +1,5 @@
//
// Copyright (C) 2003-2021 Greg Landrum and other RDKit contributors
// Copyright (C) 2003-2026 Greg Landrum and other RDKit contributors
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
@@ -265,6 +265,9 @@ class RDKIT_RDGENERAL_EXPORT Dict {
void setVal(const std::string_view what, T &val) {
static_assert(!std::is_same_v<T, std::string_view>,
"T cannot be string_view");
if (what.empty()) {
throw ValueErrorException("Cannot set value with empty key");
}
_hasNonPodData = true;
for (auto &&data : _data) {
if (data.key == what) {
@@ -280,6 +283,9 @@ class RDKIT_RDGENERAL_EXPORT Dict {
void setPODVal(const std::string_view what, T val) {
static_assert(!std::is_same_v<T, std::string_view>,
"T cannot be string_view");
if (what.empty()) {
throw ValueErrorException("Cannot set value with empty key");
}
// don't change the hasNonPodData status
for (auto &&data : _data) {
if (data.key == what) {
@@ -291,20 +297,45 @@ class RDKIT_RDGENERAL_EXPORT Dict {
_data.push_back(Pair(what, val));
}
void setVal(const std::string_view what, bool val) { setPODVal(what, val); }
void setVal(const std::string_view what, bool val) {
if (what.empty()) {
throw ValueErrorException("Cannot set value with empty key");
}
setPODVal(what, val);
}
void setVal(const std::string_view what, double val) { setPODVal(what, val); }
void setVal(const std::string_view what, double val) {
if (what.empty()) {
throw ValueErrorException("Cannot set value with empty key");
}
setPODVal(what, val);
}
void setVal(const std::string_view what, float val) { setPODVal(what, val); }
void setVal(const std::string_view what, int val) { setPODVal(what, val); }
void setVal(const std::string_view what, float val) {
if (what.empty()) {
throw ValueErrorException("Cannot set value with empty key");
}
setPODVal(what, val);
}
void setVal(const std::string_view what, int val) {
if (what.empty()) {
throw ValueErrorException("Cannot set value with empty key");
}
setPODVal(what, val);
}
void setVal(const std::string_view what, unsigned int val) {
if (what.empty()) {
throw ValueErrorException("Cannot set value with empty key");
}
setPODVal(what, val);
}
//! \overload
void setVal(const std::string_view what, const char *val) {
if (what.empty()) {
throw ValueErrorException("Cannot set value with empty key");
}
std::string h(val);
setVal(what, h);
}

View File

@@ -1,3 +1,6 @@
// Copyright (C) 2016-2026 Brian Kelley and other RDKit contributors
// @@ All Rights Reserved @@
//
// This file is part of the RDKit.
// The contents are covered by the terms of the BSD license
// which is included in the file license.txt, found at the root
@@ -75,6 +78,9 @@ class RDProps {
//! \overload
template <typename T>
void setProp(const std::string_view key, T val, bool computed = false) const {
if(key.empty()) {
throw ValueErrorException("Cannot set property with empty key");
}
if (computed) {
STR_VECT compLst;
getPropIfPresent(RDKit::detail::computedPropName, compLst);

View File

@@ -1,5 +1,5 @@
//
// Copyright (C) 2021 Greg Landrum
// Copyright (C) 2021-2026 Greg Landrum
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
@@ -11,6 +11,7 @@
#include <catch2/catch_all.hpp>
#include "Dict.h"
#include "RDProps.h"
#include "Exceptions.h"
using namespace std::string_literals;
TEST_CASE("Dict move semantics") {
@@ -70,3 +71,25 @@ TEST_CASE("RDProps move semantics") {
CHECK(!d1.hasProp("bar"s));
}
}
TEST_CASE("github #9068: properties with empty names") {
RDKit::RDProps props;
SECTION("setProp with empty key") {
CHECK_THROWS_AS(props.setProp("", 1), ValueErrorException);
}
SECTION("getProp with empty key") {
CHECK_THROWS_AS(props.getProp<int>(""), KeyErrorException);
}
SECTION("hasProp with empty key") { CHECK(!props.hasProp("")); }
SECTION("clearProp with empty key") { CHECK_NOTHROW(props.clearProp("")); }
}
TEST_CASE("github #9068: dicts with empty keys") {
RDKit::Dict dict;
SECTION("setVal with empty key") {
CHECK_THROWS_AS(dict.setVal("", 1), ValueErrorException);
}
SECTION("getVal with empty key") {
CHECK_THROWS_AS(dict.getVal<int>(""), KeyErrorException);
}
SECTION("hasVal with empty key") { CHECK(!dict.hasVal("")); }
SECTION("clearVal with empty key") { CHECK_NOTHROW(dict.clearVal("")); }
}