From af9b71081524061c6896b4058515e0cd4777d7f9 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 5 Oct 2024 15:27:14 +0200 Subject: [PATCH] OGRFeature: SetXXX() methods: more informative warning messages reporting field name and value for out-of-range values Fixes #10915 --- ogr/ogrfeature.cpp | 156 ++++++++++++++++++++++++++++----------------- 1 file changed, 96 insertions(+), 60 deletions(-) diff --git a/ogr/ogrfeature.cpp b/ogr/ogrfeature.cpp index 6b16502619ba..3a5e41afe17b 100644 --- a/ogr/ogrfeature.cpp +++ b/ogr/ogrfeature.cpp @@ -32,6 +32,7 @@ #include "ogr_feature.h" #include +#include #include #include #include @@ -2013,12 +2014,13 @@ int OGRFeature::GetFieldAsInteger(int iField) const : nFID < INT_MIN ? INT_MIN : static_cast(nFID); - if (static_cast(nVal) != nFID) + if (nVal != nFID) { - CPLError( - CE_Warning, CPLE_AppDefined, - "Integer overflow occurred when trying to return " - "64bit integer. Use GetFieldAsInteger64() instead"); + CPLError(CE_Warning, CPLE_AppDefined, + "Field %s.FID: Integer overflow occurred when " + "trying to return 64 bit integer %" PRId64 + ". Use GetFieldAsInteger64() instead", + poDefn->GetName(), static_cast(nVal)); } return nVal; } @@ -2034,7 +2036,7 @@ int OGRFeature::GetFieldAsInteger(int iField) const } } - OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); + const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); if (poFDefn == nullptr) return 0; @@ -2054,11 +2056,14 @@ int OGRFeature::GetFieldAsInteger(int iField) const : nVal64 < INT_MIN ? INT_MIN : static_cast(nVal64); - if (static_cast(nVal) != nVal64) + if (nVal != nVal64) { CPLError(CE_Warning, CPLE_AppDefined, - "Integer overflow occurred when trying to return 64bit " - "integer. Use GetFieldAsInteger64() instead"); + "Field %s.%s: Integer overflow occurred when trying to " + "return 64 bit integer %" PRId64 + ". Use GetFieldAsInteger64() instead", + poDefn->GetName(), poFDefn->GetNameRef(), + static_cast(nVal64)); } return nVal; } @@ -3472,13 +3477,15 @@ int OGR_F_GetFieldAsDateTimeEx(OGRFeatureH hFeat, int iField, int *pnYear, /* OGRFeatureGetIntegerValue() */ /************************************************************************/ -static int OGRFeatureGetIntegerValue(OGRFieldDefn *poFDefn, int nValue) +static int OGRFeatureGetIntegerValue(const OGRFeatureDefn *poDefn, + const OGRFieldDefn *poFDefn, int nValue) { if (poFDefn->GetSubType() == OFSTBoolean && nValue != 0 && nValue != 1) { CPLError(CE_Warning, CPLE_AppDefined, - "Only 0 or 1 should be passed for a OFSTBoolean subtype. " - "Considering this non-zero value as 1."); + "Field %s.%s: Only 0 or 1 should be passed for a OFSTBoolean " + "subtype. Considering non-zero value %d as 1.", + poDefn->GetName(), poFDefn->GetNameRef(), nValue); nValue = 1; } else if (poFDefn->GetSubType() == OFSTInt16) @@ -3486,15 +3493,17 @@ static int OGRFeatureGetIntegerValue(OGRFieldDefn *poFDefn, int nValue) if (nValue < -32768) { CPLError(CE_Warning, CPLE_AppDefined, - "Out-of-range value for a OFSTInt16 subtype. " - "Considering this value as -32768."); + "Field %s.%s: Out-of-range value for a OFSTInt16 subtype. " + "Considering value %d as -32768.", + poDefn->GetName(), poFDefn->GetNameRef(), nValue); nValue = -32768; } else if (nValue > 32767) { CPLError(CE_Warning, CPLE_AppDefined, - "Out-of-range value for a OFSTInt16 subtype. " - "Considering this value as 32767."); + "Field %s.%s: Out-of-range value for a OFSTInt16 subtype. " + "Considering value %d as 32767.", + poDefn->GetName(), poFDefn->GetNameRef(), nValue); nValue = 32767; } } @@ -3669,7 +3678,7 @@ char *OGRFeature::GetFieldAsSerializedJSon(int iField) const void OGRFeature::SetField(int iField, int nValue) { - OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); + const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); if (poFDefn == nullptr) return; @@ -3677,14 +3686,15 @@ void OGRFeature::SetField(int iField, int nValue) OGRFieldType eType = poFDefn->GetType(); if (eType == OFTInteger) { - pauFields[iField].Integer = OGRFeatureGetIntegerValue(poFDefn, nValue); + pauFields[iField].Integer = + OGRFeatureGetIntegerValue(poDefn, poFDefn, nValue); pauFields[iField].Set.nMarker2 = 0; pauFields[iField].Set.nMarker3 = 0; } else if (eType == OFTInteger64) { pauFields[iField].Integer64 = - OGRFeatureGetIntegerValue(poFDefn, nValue); + OGRFeatureGetIntegerValue(poDefn, poFDefn, nValue); } else if (eType == OFTReal) { @@ -3809,7 +3819,7 @@ void OGR_F_SetFieldInteger(OGRFeatureH hFeat, int iField, int nValue) void OGRFeature::SetField(int iField, GIntBig nValue) { - OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); + const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); if (poFDefn == nullptr) return; @@ -3821,11 +3831,14 @@ void OGRFeature::SetField(int iField, GIntBig nValue) : nValue > INT_MAX ? INT_MAX : static_cast(nValue); - if (static_cast(nVal32) != nValue) + if (nVal32 != nValue) { - CPLError(CE_Warning, CPLE_AppDefined, - "Integer overflow occurred when trying to set " - "32bit field."); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: integer overflow occurred when trying to set " + "%" PRId64 "as 32 bit integer.", + poDefn->GetName(), poFDefn->GetNameRef(), + static_cast(nValue)); } SetField(iField, nVal32); } @@ -3843,9 +3856,12 @@ void OGRFeature::SetField(int iField, GIntBig nValue) static_cast(std::numeric_limits::max()) || static_cast(pauFields[iField].Real) != nValue) { - CPLError(CE_Warning, CPLE_AppDefined, - "Lossy conversion occurred when trying to set " - "a real field from a 64 bit integer value."); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: Lossy conversion occurred when trying to set " + "a real field from 64 bit integer value %" PRId64 ".", + poDefn->GetName(), poFDefn->GetNameRef(), + static_cast(nValue)); } } else if (eType == OFTIntegerList) @@ -3854,11 +3870,14 @@ void OGRFeature::SetField(int iField, GIntBig nValue) : nValue > INT_MAX ? INT_MAX : static_cast(nValue); - if (static_cast(nVal32) != nValue) + if (nVal32 != nValue) { - CPLError(CE_Warning, CPLE_AppDefined, - "Integer overflow occurred when trying to set " - "32bit field."); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: Integer overflow occurred when trying to set " + "%" PRId64 " as 32 bit value.", + poDefn->GetName(), poFDefn->GetNameRef(), + static_cast(nValue)); } SetField(iField, 1, &nVal32); } @@ -3977,7 +3996,7 @@ void OGR_F_SetFieldInteger64(OGRFeatureH hFeat, int iField, GIntBig nValue) void OGRFeature::SetField(int iField, double dfValue) { - OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); + const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); if (poFDefn == nullptr) return; @@ -4001,9 +4020,11 @@ void OGRFeature::SetField(int iField, double dfValue) if (std::isnan(dfValue)) { pauFields[iField].Integer = nMin; - CPLError(CE_Warning, CPLE_AppDefined, - "Lossy conversion occurred when trying to set " - "32 bit integer field from a real value."); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: Lossy conversion occurred when trying to set " + "32 bit integer field from real value %.17g.", + poDefn->GetName(), poFDefn->GetNameRef(), dfValue); } else { @@ -4012,12 +4033,14 @@ void OGRFeature::SetField(int iField, double dfValue) : dfValue > nMax ? nMax : static_cast(dfValue); pauFields[iField].Integer = - OGRFeatureGetIntegerValue(poFDefn, nVal); + OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal); if (!(nVal == dfValue)) { - CPLError(CE_Warning, CPLE_AppDefined, - "Lossy conversion occurred when trying to set " - "32 bit integer field from a real value."); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: Lossy conversion occurred when trying to set " + "32 bit integer field from real value %.17g.", + poDefn->GetName(), poFDefn->GetNameRef(), dfValue); } } pauFields[iField].Set.nMarker2 = 0; @@ -4029,9 +4052,11 @@ void OGRFeature::SetField(int iField, double dfValue) if (std::isnan(dfValue)) { pauFields[iField].Integer64 = nMin; - CPLError(CE_Warning, CPLE_AppDefined, - "Lossy conversion occurred when trying to set " - "64 bit integer field from a real value."); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: Lossy conversion occurred when trying to set " + "64 bit integer field from real value %.17g.", + poDefn->GetName(), poFDefn->GetNameRef(), dfValue); } else { @@ -4043,9 +4068,11 @@ void OGRFeature::SetField(int iField, double dfValue) pauFields[iField].Integer64 = nVal; if (!(static_cast(nVal) == dfValue)) { - CPLError(CE_Warning, CPLE_AppDefined, - "Lossy conversion occurred when trying to set " - "64 bit integer field from a real value."); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: Lossy conversion occurred when trying to set " + "64 bit integer field from real value %.17g.", + poDefn->GetName(), poFDefn->GetNameRef(), dfValue); } } pauFields[iField].Set.nMarker3 = 0; @@ -4174,7 +4201,7 @@ void OGRFeature::SetField(int iField, const char *pszValue) bWarn = CPLTestBool( CPLGetConfigOption("OGR_SETFIELD_NUMERIC_WARNING", "YES")); - OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); + const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); if (poFDefn == nullptr) return; @@ -4249,7 +4276,7 @@ void OGRFeature::SetField(int iField, const char *pszValue) : nVal64 < INT_MIN ? INT_MIN : static_cast(nVal64); pauFields[iField].Integer = - OGRFeatureGetIntegerValue(poFDefn, nVal32); + OGRFeatureGetIntegerValue(poDefn, poFDefn, nVal32); if (bWarn && pauFields[iField].Integer == nVal32 && (errno == ERANGE || nVal32 != nVal64 || !pszLast || *pszLast)) CPLError(CE_Warning, CPLE_AppDefined, @@ -4357,7 +4384,9 @@ void OGRFeature::SetField(int iField, const char *pszValue) { CPLError( CE_Warning, CPLE_AppDefined, - "32 bit integer overflow when converting %s", + "Field %s.%s: 32 bit integer overflow when " + "converting %s", + poDefn->GetName(), poFDefn->GetNameRef(), pszValue); } anValues.push_back(nVal); @@ -4525,7 +4554,7 @@ void OGR_F_SetFieldString(OGRFeatureH hFeat, int iField, const char *pszValue) void OGRFeature::SetField(int iField, int nCount, const int *panValues) { - OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); + const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); if (poFDefn == nullptr) return; @@ -4541,7 +4570,8 @@ void OGRFeature::SetField(int iField, int nCount, const int *panValues) { for (int i = 0; i < nCount; i++) { - int nVal = OGRFeatureGetIntegerValue(poFDefn, panValues[i]); + int nVal = + OGRFeatureGetIntegerValue(poDefn, poFDefn, panValues[i]); if (panValues[i] != nVal) { if (panValuesMod == nullptr) @@ -4682,7 +4712,7 @@ void OGR_F_SetFieldIntegerList(OGRFeatureH hFeat, int iField, int nCount, void OGRFeature::SetField(int iField, int nCount, const GIntBig *panValues) { - OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); + const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField); if (poFDefn == nullptr) return; @@ -4699,11 +4729,14 @@ void OGRFeature::SetField(int iField, int nCount, const GIntBig *panValues) : nValue > INT_MAX ? INT_MAX : static_cast(nValue); - if (static_cast(nVal32) != nValue) + if (nVal32 != nValue) { - CPLError(CE_Warning, CPLE_AppDefined, - "Integer overflow occurred when trying to set " - "32bit field."); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: Integer overflow occurred when trying to " + "set %" PRId64 " as 32 bit value.", + poDefn->GetName(), poFDefn->GetNameRef(), + static_cast(nValue)); } anValues.push_back(nVal32); } @@ -4991,9 +5024,10 @@ void OGRFeature::SetField(int iField, const char *const *papszValues) int nVal = atoi(papszValues[i]); if (errno == ERANGE) { - CPLError(CE_Warning, CPLE_AppDefined, - "32 bit integer overflow when converting %s", - papszValues[i]); + CPLError( + CE_Warning, CPLE_AppDefined, + "Field %s.%s: 32 bit integer overflow when converting %s", + poDefn->GetName(), poFDefn->GetNameRef(), papszValues[i]); if (papszValues[i][0] == '-') nVal = INT_MIN; else @@ -7132,7 +7166,8 @@ int OGRFeature::Validate(int nValidateFlags, int bEmitError) const if (bEmitError) { CPLError(CE_Failure, CPLE_AppDefined, - "Field %s has a NULL content which is not allowed", + "Field %s.%s has a NULL content which is not allowed", + poDefn->GetName(), poDefn->GetFieldDefn(i)->GetNameRef()); } } @@ -7147,8 +7182,9 @@ int OGRFeature::Validate(int nValidateFlags, int bEmitError) const if (bEmitError) { CPLError(CE_Failure, CPLE_AppDefined, - "Field %s has a %d UTF-8 characters whereas " + "Field %s.%s has a %d UTF-8 characters whereas " "a maximum of %d is allowed", + poDefn->GetName(), poDefn->GetFieldDefn(i)->GetNameRef(), CPLStrlenUTF8(GetFieldAsString(i)), poDefn->GetFieldDefn(i)->GetWidth());