From 7f3b333815cf1d515e7d77a1561d83890182d2a4 Mon Sep 17 00:00:00 2001 From: MarkLee131 Date: Tue, 7 Apr 2026 00:39:16 +0800 Subject: [PATCH 1/3] fix GetColumnNames() undefined behavior on empty label row GetColumnNames() did .begin() + (mRowNameIdx + 1) on the label row without checking that the row has enough elements. When the label row is empty (e.g. after InsertRow on an empty document with LabelParams(0,0)), .begin() wraps a null pointer and adding to it is undefined behavior. Add a bounds check before the iterator arithmetic so it returns an empty vector instead of hitting UB. --- src/rapidcsv.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/rapidcsv.h b/src/rapidcsv.h index bc83e0e..53e1f58 100644 --- a/src/rapidcsv.h +++ b/src/rapidcsv.h @@ -1473,9 +1473,13 @@ namespace rapidcsv { if (mLabelParams.mColumnNameIdx >= 0) { - return std::vector(mData.at(static_cast(mLabelParams.mColumnNameIdx)).begin() + - (mLabelParams.mRowNameIdx + 1), - mData.at(static_cast(mLabelParams.mColumnNameIdx)).end()); + const auto& labelRow = mData.at(static_cast(mLabelParams.mColumnNameIdx)); + const size_t offset = static_cast(mLabelParams.mRowNameIdx + 1); + if (offset <= labelRow.size()) + { + return std::vector(labelRow.begin() + static_cast(offset), + labelRow.end()); + } } return std::vector(); From 30271a046df03df256dbbfc7be93934a61f5ab88 Mon Sep 17 00:00:00 2001 From: Kristofer Berggren Date: Sun, 12 Apr 2026 12:39:47 +0800 Subject: [PATCH 2/3] add test for get column labels of empty label row --- CMakeLists.txt | 1 + tests/test107.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/test107.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 31e21ed..b4d1564 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,6 +196,7 @@ if(RAPIDCSV_BUILD_TESTS) add_unit_test(test104) add_unit_test(test105) add_unit_test(test106) + add_unit_test(test107) # perf tests add_perf_test(ptest001) diff --git a/tests/test107.cpp b/tests/test107.cpp new file mode 100644 index 0000000..7114454 --- /dev/null +++ b/tests/test107.cpp @@ -0,0 +1,31 @@ +// test107.cpp - get column labels of empty label row + +#include +#include "unittest.h" + +int main() +{ + int rv = 0; + + try + { + // Empty document, specify column and row labels available + std::string csv = ""; + std::istringstream s(csv); + rapidcsv::Document doc(s, rapidcsv::LabelParams(0, 0)); + + // InsertRow create a row with 0 columns + doc.InsertRow(0); + + // Get column names + std::vector names = doc.GetColumnNames(); + unittest::ExpectEqual(size_t, names.size(), size_t(0)); + } + catch (const std::exception& ex) + { + std::cout << "exception: " << ex.what() << std::endl; + rv = 1; + } + + return rv; +} From 8335635653d024f3c7ed6341f4b966bb1dc2262f Mon Sep 17 00:00:00 2001 From: Kristofer Berggren Date: Sun, 12 Apr 2026 12:46:56 +0800 Subject: [PATCH 3/3] minor code style change, bump version --- src/rapidcsv.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/rapidcsv.h b/src/rapidcsv.h index 53e1f58..3111db9 100644 --- a/src/rapidcsv.h +++ b/src/rapidcsv.h @@ -2,7 +2,7 @@ * rapidcsv.h * * URL: https://github.com/d99kris/rapidcsv - * Version: 8.95 + * Version: 8.96 * * Copyright (C) 2017-2026 Kristofer Berggren * All rights reserved. @@ -1473,12 +1473,11 @@ namespace rapidcsv { if (mLabelParams.mColumnNameIdx >= 0) { - const auto& labelRow = mData.at(static_cast(mLabelParams.mColumnNameIdx)); + const std::vector& labelRow = mData.at(static_cast(mLabelParams.mColumnNameIdx)); const size_t offset = static_cast(mLabelParams.mRowNameIdx + 1); if (offset <= labelRow.size()) { - return std::vector(labelRow.begin() + static_cast(offset), - labelRow.end()); + return std::vector(labelRow.begin() + static_cast(offset), labelRow.end()); } }