Fix undefined behaviour by bit-shifting with negative value.
authorHyunjun Ko <zzoon@igalia.com>
Tue, 16 Aug 2022 09:34:12 +0000 (18:34 +0900)
committerMatthew Netsch <quic_mnetsch@quicinc.com>
Thu, 18 Aug 2022 17:26:52 +0000 (17:26 +0000)
When getTextureFormatMantissaBitDepth returns 0 for the non-existent channels,
it leads to 1u << (0u - 1u), that is undefined behaviour, especially
leads to unexpected results on arm64.

Affects:
dEQP-VK.image.store.*
dEQP-VK.image.load_store.*
dEQP-VK.image.format_reinterpret.*

Components: Vulkan

VK-GL-CTS issue: 3888

Change-Id: I669eebb1f78c78dc89fb456e71f2ca0af3b66836

external/vulkancts/modules/vulkan/image/vktImageLoadStoreTests.cpp

index 45abcda..83289a1 100644 (file)
@@ -51,6 +51,7 @@
 #include "tcuTextureUtil.hpp"
 #include "tcuFloat.hpp"
 #include "tcuStringTemplate.hpp"
+#include "tcuVectorUtil.hpp"
 
 #include <string>
 #include <vector>
@@ -179,8 +180,12 @@ bool comparePixelBuffers (tcu::TestLog&                                            log,
 
                        case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
                        {
+                               const tcu::UVec4 bitDepth = tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u;
+                               // To avoid bit-shifting with negative value, which is undefined behaviour.
+                               const tcu::UVec4 fixedBitDepth = tcu::select(bitDepth, tcu::UVec4(0u, 0u, 0u, 0u), tcu::greaterThanEqual(bitDepth.cast<deInt32>(), tcu::IVec4(0, 0, 0, 0)));
+
                                // Allow error of minimum representable difference
-                               const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << (tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u)) - 1u).cast<float>());
+                               const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << fixedBitDepth) - 1u).cast<float>());
 
                                ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
                                break;