From 185ca149b67087dae275f43fa6fec219ad50a405 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 1 Oct 2024 00:41:52 +0200 Subject: [PATCH] CPLGetValueType(): do not recognize '01' as integer, but as string Fixes https://github.com/Toblerity/Fiona/issues/1454 --- apps/gdaltransform.cpp | 5 +++++ autotest/cpp/test_cpl.cpp | 15 ++++++++------- ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp | 4 +++- port/cpl_string.cpp | 4 ++++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/apps/gdaltransform.cpp b/apps/gdaltransform.cpp index 7dea9f3bbb48..5c835b559bee 100644 --- a/apps/gdaltransform.cpp +++ b/apps/gdaltransform.cpp @@ -402,6 +402,11 @@ MAIN_START(argc, argv) if (fgets(szLine, sizeof(szLine) - 1, stdin) == nullptr) break; + size_t nLen = strlen(szLine); + if (nLen && szLine[nLen - 1] == '\n') + szLine[--nLen] = 0; + if (nLen && szLine[nLen - 1] == '\r') + szLine[--nLen] = 0; const CPLStringList aosTokens(CSLTokenizeString(szLine)); const int nCount = aosTokens.size(); diff --git a/autotest/cpp/test_cpl.cpp b/autotest/cpp/test_cpl.cpp index 9701f8922cb2..7861eb31da44 100644 --- a/autotest/cpp/test_cpl.cpp +++ b/autotest/cpp/test_cpl.cpp @@ -163,7 +163,7 @@ typedef struct // Test CPLGetValueType TEST_F(test_cpl, CPLGetValueType) { - TestStringStruct apszTestStrings[] = { + TestStringStruct asTestStrings[] = { {"+25.e+3", CPL_VALUE_REAL}, {"-25.e-3", CPL_VALUE_REAL}, {"25.e3", CPL_VALUE_REAL}, {"25e3", CPL_VALUE_REAL}, {" 25e3 ", CPL_VALUE_REAL}, {".1e3", CPL_VALUE_REAL}, @@ -176,15 +176,16 @@ TEST_F(test_cpl, CPLGetValueType) {"25.25.3", CPL_VALUE_STRING}, {"25e25e3", CPL_VALUE_STRING}, {"25e2500", CPL_VALUE_STRING}, /* #6128 */ - {"d1", CPL_VALUE_STRING} /* #6305 */ + {"d1", CPL_VALUE_STRING}, /* #6305 */ + + {"01", CPL_VALUE_STRING}, {"0.1", CPL_VALUE_REAL}, + {"0", CPL_VALUE_INTEGER}, }; - size_t i; - for (i = 0; i < sizeof(apszTestStrings) / sizeof(apszTestStrings[0]); i++) + for (const auto &sText : asTestStrings) { - EXPECT_EQ(CPLGetValueType(apszTestStrings[i].testString), - apszTestStrings[i].expectedResult) - << apszTestStrings[i].testString; + EXPECT_EQ(CPLGetValueType(sText.testString), sText.expectedResult) + << sText.testString; } } diff --git a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp index ba3194e5e3ac..98a3a574ef69 100644 --- a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp +++ b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp @@ -2405,7 +2405,9 @@ OGRErr OGRCSVLayer::ICreateFeature(OGRFeature *poNewFeature) pszContent, -1, (m_eStringQuoting == StringQuoting::ALWAYS || (m_eStringQuoting == StringQuoting::IF_AMBIGUOUS && - CPLGetValueType(pszContent) != CPL_VALUE_STRING)) + (CPLGetValueType(pszContent) != CPL_VALUE_STRING || + (pszContent[0] == DIGIT_ZERO && pszContent[1] != '\0' && + pszContent[1] != '.')))) ? CPLES_CSV_FORCE_QUOTING : CPLES_CSV); } diff --git a/port/cpl_string.cpp b/port/cpl_string.cpp index f7372c29f7cd..06a44ad4d8ed 100644 --- a/port/cpl_string.cpp +++ b/port/cpl_string.cpp @@ -2791,6 +2791,10 @@ CPLValueType CPLGetValueType(const char *pszValue) if (*pszValue == '+' || *pszValue == '-') ++pszValue; + constexpr char DIGIT_ZERO = '0'; + if (pszValue[0] == DIGIT_ZERO && pszValue[1] != '\0' && pszValue[1] != '.') + return CPL_VALUE_STRING; + bool bFoundDot = false; bool bFoundExponent = false; bool bIsLastCharExponent = false;