Skip to content

Commit

Permalink
OGRFeature: SetXXX() methods: more informative warning messages repor…
Browse files Browse the repository at this point in the history
…ting field name and value for out-of-range values

Fixes #10915
  • Loading branch information
rouault committed Oct 5, 2024
1 parent d09bdd0 commit ee44817
Showing 1 changed file with 95 additions and 58 deletions.
153 changes: 95 additions & 58 deletions ogr/ogrfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "ogr_feature.h"

#include <cerrno>
#include <cinttypes>
#include <climits>
#include <cstdio>
#include <cstdlib>
Expand Down Expand Up @@ -2013,12 +2014,14 @@ int OGRFeature::GetFieldAsInteger(int iField) const
: nFID < INT_MIN ? INT_MIN
: static_cast<int>(nFID);

if (static_cast<GIntBig>(nVal) != nFID)
if (nVal != nFID)
{
CPLError(
CE_Warning, CPLE_AppDefined,
"Integer overflow occurred when trying to return "
"64bit integer. Use GetFieldAsInteger64() instead");
"Field FID: Integer overflow occurred when trying to "
"return 64 bit integer %" PRId64
". Use GetFieldAsInteger64() instead",
static_cast<int64_t>(nVal));
}
return nVal;
}
Expand All @@ -2034,7 +2037,7 @@ int OGRFeature::GetFieldAsInteger(int iField) const
}
}

OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
const OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);

if (poFDefn == nullptr)
return 0;
Expand All @@ -2054,11 +2057,14 @@ int OGRFeature::GetFieldAsInteger(int iField) const
: nVal64 < INT_MIN ? INT_MIN
: static_cast<int>(nVal64);

if (static_cast<GIntBig>(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<int64_t>(nVal64));
}
return nVal;
}
Expand Down Expand Up @@ -3472,29 +3478,33 @@ 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)
{
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;
}
}
Expand Down Expand Up @@ -3669,22 +3679,23 @@ 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;

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)
{
Expand Down Expand Up @@ -3809,7 +3820,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;
Expand All @@ -3821,11 +3832,14 @@ void OGRFeature::SetField(int iField, GIntBig nValue)
: nValue > INT_MAX ? INT_MAX
: static_cast<int>(nValue);

if (static_cast<GIntBig>(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<int64_t>(nValue));
}
SetField(iField, nVal32);
}
Expand All @@ -3843,9 +3857,12 @@ void OGRFeature::SetField(int iField, GIntBig nValue)
static_cast<double>(std::numeric_limits<int64_t>::max()) ||
static_cast<GIntBig>(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<int64_t>(nValue));
}
}
else if (eType == OFTIntegerList)
Expand All @@ -3854,11 +3871,14 @@ void OGRFeature::SetField(int iField, GIntBig nValue)
: nValue > INT_MAX ? INT_MAX
: static_cast<int>(nValue);

if (static_cast<GIntBig>(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<int64_t>(nValue));
}
SetField(iField, 1, &nVal32);
}
Expand Down Expand Up @@ -3977,7 +3997,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;
Expand All @@ -4001,9 +4021,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
{
Expand All @@ -4012,12 +4034,14 @@ void OGRFeature::SetField(int iField, double dfValue)
: dfValue > nMax ? nMax
: static_cast<int>(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;
Expand All @@ -4029,9 +4053,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
{
Expand All @@ -4043,9 +4069,11 @@ void OGRFeature::SetField(int iField, double dfValue)
pauFields[iField].Integer64 = nVal;
if (!(static_cast<double>(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;
Expand Down Expand Up @@ -4174,7 +4202,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;

Expand Down Expand Up @@ -4249,7 +4277,7 @@ void OGRFeature::SetField(int iField, const char *pszValue)
: nVal64 < INT_MIN ? INT_MIN
: static_cast<int>(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,
Expand Down Expand Up @@ -4357,7 +4385,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);
Expand Down Expand Up @@ -4525,7 +4555,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;
Expand All @@ -4541,7 +4571,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)
Expand Down Expand Up @@ -4682,7 +4713,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;
Expand All @@ -4699,11 +4730,14 @@ void OGRFeature::SetField(int iField, int nCount, const GIntBig *panValues)
: nValue > INT_MAX ? INT_MAX
: static_cast<int>(nValue);

if (static_cast<GIntBig>(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<int64_t>(nValue));
}
anValues.push_back(nVal32);
}
Expand Down Expand Up @@ -4991,9 +5025,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
Expand Down Expand Up @@ -7137,7 +7172,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());
}
}
Expand All @@ -7152,8 +7188,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());
Expand Down

0 comments on commit ee44817

Please sign in to comment.