From bb9066d5e047940830ac0984f876d65077ebf42b Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 19 Mar 2024 21:41:11 +0100 Subject: [PATCH] GPKG: avoid invalide use of pointer aliasing that caused ICC 2024.0.2.29 to generate invalid code (refs #9508) --- .../gpkg/gdalgeopackagerasterband.cpp | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp b/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp index ad585abff65e..a278f59990d3 100644 --- a/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp +++ b/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp @@ -508,19 +508,20 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile( for (size_t i = 0; i < static_cast(nBlockXSize) * nBlockYSize; i++) { - const GUInt16 nVal = *reinterpret_cast( - pabyTileData + i * sizeof(GUInt16)); + GUInt16 usVal; + memcpy(&usVal, pabyTileData + i * sizeof(GUInt16), + sizeof(usVal)); double dfVal = - floor((nVal * dfTileScale + dfTileOffset) * m_dfScale + + floor((usVal * dfTileScale + dfTileOffset) * m_dfScale + m_dfOffset + 0.5); - if (bHasNoData && nVal == m_usGPKGNull) + if (bHasNoData && usVal == m_usGPKGNull) dfVal = dfNoDataValue; if (dfVal > 32767) dfVal = 32767; else if (dfVal < -32768) dfVal = -32768; - *reinterpret_cast(pabyTileData + i * sizeof(GInt16)) = - static_cast(dfVal); + GInt16 sVal = static_cast(dfVal); + memcpy(pabyTileData + i * sizeof(GUInt16), &sVal, sizeof(sVal)); } } else if (m_eDT == GDT_UInt16 && @@ -528,11 +529,11 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile( dfTileOffset != 0.0 || dfTileScale != 1.0)) { CPLAssert(eRequestDT == GDT_UInt16); + GUInt16 *psVal = reinterpret_cast(pabyTileData); for (size_t i = 0; i < static_cast(nBlockXSize) * nBlockYSize; i++) { - const GUInt16 nVal = *reinterpret_cast( - pabyTileData + i * sizeof(GUInt16)); + const GUInt16 nVal = psVal[i]; double dfVal = floor((nVal * dfTileScale + dfTileOffset) * m_dfScale + m_dfOffset + 0.5); @@ -542,9 +543,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile( dfVal = 65535; else if (dfVal < 0) dfVal = 0; - *reinterpret_cast(pabyTileData + - i * sizeof(GUInt16)) = - static_cast(dfVal); + psVal[i] = static_cast(dfVal); } } else if (m_eDT == GDT_Float32 && eRequestDT == GDT_UInt16) @@ -555,16 +554,21 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile( static_cast(nBlockXSize) * nBlockYSize - 1; i >= 0; i--) { - const GUInt16 nVal = *reinterpret_cast( - pabyTileData + i * sizeof(GUInt16)); - double dfVal = (nVal * dfTileScale + dfTileOffset) * m_dfScale + - m_dfOffset; + // Use memcpy() and not reinterpret_cast and + // reinterpret_cast, otherwise compilers such as ICC + // may (ab)use rules about aliasing to generate wrong code! + GUInt16 usVal; + memcpy(&usVal, pabyTileData + i * sizeof(GUInt16), + sizeof(usVal)); + double dfVal = + (usVal * dfTileScale + dfTileOffset) * m_dfScale + + m_dfOffset; if (m_dfPrecision == 1.0) dfVal = floor(dfVal + 0.5); - if (bHasNoData && nVal == m_usGPKGNull) + if (bHasNoData && usVal == m_usGPKGNull) dfVal = dfNoDataValue; - *reinterpret_cast(pabyTileData + i * sizeof(float)) = - static_cast(dfVal); + const float fVal = static_cast(dfVal); + memcpy(pabyTileData + i * sizeof(float), &fVal, sizeof(fVal)); } }