From ac824edfb0c522ebdb861ea3c613e570289d5ffd Mon Sep 17 00:00:00 2001 From: Matt Jones <47545907+SoundMatt@users.noreply.github.com> Date: Fri, 22 May 2026 11:29:37 -0700 Subject: [PATCH] fix: guard optional accesses and numeric parse calls against absent/malformed values Four related issues where WebSocket-derived values could be absent or non-numeric: (a) node.getValue().value() in generateTriplesFromNode now checks has_value() first; (b) coordinate getValue().value() calls in generateTriplesFromCoordinates are guarded similarly; (c) std::stod in getCoordInNtm is wrapped in try/catch returning std::nullopt on failure; (d) std::stoi in parseISO8601ToTime is wrapped in try/catch assigning std::nullopt to milliseconds on failure. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com> --- .../rdf-writer/src/triple_assembler.cpp | 12 ++++++++++++ cdsp/knowledge-layer/connector/utils/helper.cpp | 14 +++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/cdsp/knowledge-layer/connector/json-rdf-convertor/rdf-writer/src/triple_assembler.cpp b/cdsp/knowledge-layer/connector/json-rdf-convertor/rdf-writer/src/triple_assembler.cpp index 5752332f..da7d9d25 100644 --- a/cdsp/knowledge-layer/connector/json-rdf-convertor/rdf-writer/src/triple_assembler.cpp +++ b/cdsp/knowledge-layer/connector/json-rdf-convertor/rdf-writer/src/triple_assembler.cpp @@ -226,6 +226,9 @@ void TripleAssembler::generateTriplesFromNode(const Node& node, const SchemaType const auto node_timestamp = getTimestampFromNode(node); + if (!node.getValue().has_value()) { + throw std::runtime_error("Node value is absent for node: " + node.getName()); + } triple_writer_.addElementDataToTriple(prefixes, data_values, node.getValue().value(), node_timestamp, ntm_coord_value); } catch (const std::exception& e) { @@ -255,6 +258,15 @@ void TripleAssembler::generateTriplesFromCoordinates( const DataMessage& message) { { try { + if (!valid_coordinates.has_value()) { + throw std::runtime_error("Coordinate pair is absent"); + } + if (!valid_coordinates.value().latitude.getValue().has_value()) { + throw std::runtime_error("Latitude value is absent"); + } + if (!valid_coordinates.value().longitude.getValue().has_value()) { + throw std::runtime_error("Longitude value is absent"); + } auto ntm_coord = Helper::getCoordInNtm(valid_coordinates.value().latitude.getValue().value(), valid_coordinates.value().longitude.getValue().value()); diff --git a/cdsp/knowledge-layer/connector/utils/helper.cpp b/cdsp/knowledge-layer/connector/utils/helper.cpp index ddbc1f6a..bff65e05 100644 --- a/cdsp/knowledge-layer/connector/utils/helper.cpp +++ b/cdsp/knowledge-layer/connector/utils/helper.cpp @@ -125,7 +125,11 @@ std::tuple, std::optional> Helper::parseISO8601ToTim // Check for milliseconds in the format .sss if (iso_string.find('.') != std::string::npos) { std::string millisStr = iso_string.substr(iso_string.find('.') + 1, 3); - milliseconds = std::stoi(millisStr); + try { + milliseconds = std::stoi(millisStr); + } catch (const std::exception&) { + milliseconds = std::nullopt; + } } return {tm, milliseconds}; @@ -204,8 +208,12 @@ std::optional Helper::getCoordInNtm(const std::string& latitude, } Wgs84Coord coord_to_convert; - coord_to_convert.latitude = std::stod(latitude); - coord_to_convert.longitude = std::stod(longitude); + try { + coord_to_convert.latitude = std::stod(latitude); + coord_to_convert.longitude = std::stod(longitude); + } catch (const std::exception&) { + return std::nullopt; + } return CoordinateTransform::ntmPoseFromWgs84(ZONE_ORIGIN, coord_to_convert); }