[val] Fix crash evaluating >64-bit integer constants in EvalConstantVal{Uint,Int}64 (#6816)
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index fe57eea..c118fd6 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -1876,10 +1876,12 @@
     return false;
   } else if (inst->words().size() == 4) {
     *val = inst->word(3);
-  } else {
-    assert(inst->words().size() == 5);
+  } else if (inst->words().size() == 5) {
     *val = inst->word(3);
     *val |= uint64_t(inst->word(4)) << 32;
+  } else {
+    // Literal value wider than 64 bits does not fit in a uint64_t.
+    return false;
   }
   return true;
 }
@@ -1922,11 +1924,13 @@
     return false;
   } else if (inst->words().size() == 4) {
     *val = int32_t(inst->word(3));
-  } else {
-    assert(inst->words().size() == 5);
+  } else if (inst->words().size() == 5) {
     const uint32_t lo_word = inst->word(3);
     const uint32_t hi_word = inst->word(4);
     *val = static_cast<int64_t>(uint64_t(lo_word) | uint64_t(hi_word) << 32);
+  } else {
+    // Literal value wider than 64 bits does not fit in an int64_t.
+    return false;
   }
   return true;
 }
diff --git a/test/val/val_extension_spv_intel_arbitrary_precision_integers_test.cpp b/test/val/val_extension_spv_intel_arbitrary_precision_integers_test.cpp
index c21bfc8..b8f4ea9 100644
--- a/test/val/val_extension_spv_intel_arbitrary_precision_integers_test.cpp
+++ b/test/val/val_extension_spv_intel_arbitrary_precision_integers_test.cpp
@@ -15,14 +15,21 @@
 // Tests for SPV_INTEL_arbitrary_precision_integers extension
 
 #include <string>
+#include <vector>
 
 #include "gmock/gmock.h"
+#include "source/opcode.h"
+#include "source/util/string_utils.h"
+#include "test/unit_spirv.h"
 #include "test/val/val_fixtures.h"
 
 namespace spvtools {
 namespace val {
 namespace {
 
+using ::spvtest::Concatenate;
+using ::spvtest::MakeInstruction;
+using ::spvtest::ScopedContext;
 using ::testing::HasSubstr;
 
 using ValidateIntelArbitraryPrecisionIntegers = spvtest::ValidateBase<bool>;
@@ -173,6 +180,45 @@
   EXPECT_THAT(getDiagnosticString(), HasSubstr("OpTypeInt has 0 bits"));
 }
 
+// Built as a raw binary since the assembler rejects integer literals wider
+// than 64 bits.
+TEST_F(ValidateIntelArbitraryPrecisionIntegers,
+       WideIntegerConstantAsArrayLengthDoesNotCrash) {
+  const uint32_t kInt128Id = 1;
+  const uint32_t kConstId = 2;
+  const uint32_t kFloatId = 3;
+  const uint32_t kArrayId = 4;
+
+  std::vector<uint32_t> words = Concatenate({
+      {spv::MagicNumber, 0x10000, 0u, 5u /* id bound */, 0u},
+      MakeInstruction(spv::Op::OpCapability,
+                      {uint32_t(spv::Capability::Shader)}),
+      MakeInstruction(
+          spv::Op::OpCapability,
+          {uint32_t(spv::Capability::ArbitraryPrecisionIntegersINTEL)}),
+      MakeInstruction(spv::Op::OpCapability,
+                      {uint32_t(spv::Capability::Linkage)}),
+      MakeInstruction(
+          spv::Op::OpExtension,
+          utils::MakeVector("SPV_INTEL_arbitrary_precision_integers")),
+      MakeInstruction(spv::Op::OpMemoryModel,
+                      {uint32_t(spv::AddressingModel::Logical),
+                       uint32_t(spv::MemoryModel::GLSL450)}),
+      MakeInstruction(spv::Op::OpTypeInt, {kInt128Id, 128u, 0u}),
+      // A 128-bit OpConstant carries 4 literal words (16 bytes).
+      MakeInstruction(spv::Op::OpConstant,
+                      {kInt128Id, kConstId, 4u, 0u, 0u, 0u}),
+      MakeInstruction(spv::Op::OpTypeFloat, {kFloatId, 32u}),
+      MakeInstruction(spv::Op::OpTypeArray, {kArrayId, kFloatId, kConstId}),
+  });
+
+  spv_diagnostic diagnostic = nullptr;
+  spv_const_binary_t binary{words.data(), words.size()};
+  ScopedContext context;
+  EXPECT_EQ(SPV_SUCCESS, spvValidate(context.context, &binary, &diagnostic));
+  spvDiagnosticDestroy(diagnostic);
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/test/val/val_validation_state_test.cpp b/test/val/val_validation_state_test.cpp
index 05a5de4..0a9b4ef 100644
--- a/test/val/val_validation_state_test.cpp
+++ b/test/val/val_validation_state_test.cpp
@@ -15,9 +15,11 @@
 // Basic tests for the ValidationState_t datastructure.
 
 #include <string>
+#include <vector>
 
 #include "gmock/gmock.h"
 #include "source/spirv_validator_options.h"
+#include "source/util/string_utils.h"
 #include "test/unit_spirv.h"
 #include "test/val/val_fixtures.h"
 
@@ -307,6 +309,45 @@
                         " %1 = OpFunction %void Pure|Const %3\n"));
 }
 
+TEST_F(ValidationStateTest, EvalConstantValWiderThan64BitsIsNotEvaluable) {
+  const uint32_t kInt128Id = 1;
+  const uint32_t kConstId = 2;
+
+  std::vector<uint32_t> words = spvtest::Concatenate({
+      {spv::MagicNumber, 0x10000, 0u, 3u /* id bound */, 0u},
+      spvtest::MakeInstruction(spv::Op::OpCapability,
+                               {uint32_t(spv::Capability::Shader)}),
+      spvtest::MakeInstruction(
+          spv::Op::OpCapability,
+          {uint32_t(spv::Capability::ArbitraryPrecisionIntegersINTEL)}),
+      spvtest::MakeInstruction(spv::Op::OpCapability,
+                               {uint32_t(spv::Capability::Linkage)}),
+      spvtest::MakeInstruction(
+          spv::Op::OpExtension,
+          utils::MakeVector("SPV_INTEL_arbitrary_precision_integers")),
+      spvtest::MakeInstruction(spv::Op::OpMemoryModel,
+                               {uint32_t(spv::AddressingModel::Logical),
+                                uint32_t(spv::MemoryModel::GLSL450)}),
+      spvtest::MakeInstruction(spv::Op::OpTypeInt, {kInt128Id, 128u, 0u}),
+      spvtest::MakeInstruction(spv::Op::OpConstant,
+                               {kInt128Id, kConstId, 4u, 0u, 0u, 0u}),
+  });
+
+  spv_diagnostic diagnostic = nullptr;
+  spvtest::ScopedContext context;
+  EXPECT_EQ(SPV_SUCCESS,
+            spvtools::val::ValidateBinaryAndKeepValidationState(
+                context.context, getValidatorOptions(), words.data(),
+                words.size(), &diagnostic, &vstate_));
+  spvDiagnosticDestroy(diagnostic);
+
+  uint64_t uval = 0xdeadbeef;
+  EXPECT_FALSE(vstate_->EvalConstantValUint64(kConstId, &uval));
+
+  int64_t ival = 0xdeadbeef;
+  EXPECT_FALSE(vstate_->EvalConstantValInt64(kConstId, &ival));
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools