Avoid read past end of operands vector for EOpFrexp
When emitting SPIR-V code for frexp, avoid access
beyond the end of the operands vector. When constructing
the OpExtInst, construct a new arguments vector instead of
modifying the existing operands vector. In the case of OpFrexp,
well need that last operand later on to generate the store.
Fixes https://github.com/KhronosGroup/glslang/issues/110
Change-Id: Ibc380fadf5e600ac491932e9ecef7afe2d72fd7f
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 1d77b02..0fff30e 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -2893,9 +2893,11 @@
spv::Id id = 0;
if (libCall >= 0) {
- while (consumedOperands < (int)operands.size())
- operands.pop_back();
- id = builder.createBuiltinCall(precision, typeId, stdBuiltins, libCall, operands);
+ // Use an extended instruction from the standard library.
+ // Construct the call arguments, without modifying the original operands vector.
+ // We might need the remaining arguments, e.g. in the EOpFrexp case.
+ std::vector<spv::Id> callArguments(operands.begin(), operands.begin() + consumedOperands);
+ id = builder.createBuiltinCall(precision, typeId, stdBuiltins, libCall, callArguments);
} else {
switch (consumedOperands) {
case 0:
@@ -2930,6 +2932,7 @@
builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
break;
case glslang::EOpFrexp:
+ assert(operands.size() == 2);
builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]);
id = builder.createCompositeExtract(id, typeId0, 0);
break;