Avoid out of range access to spirv data.

Avoids debug assertion crashes on MSVC 2015 when trying to access
elements out of range.
This commit is contained in:
Hans-Kristian Arntzen 2016-04-11 13:38:18 +02:00
parent 147e53aeb2
commit 5ac882765d
3 changed files with 18 additions and 12 deletions

View File

@ -60,7 +60,7 @@ bool Compiler::block_is_pure(const SPIRBlock &block)
{
for (auto &i : block.ops)
{
auto ops = stream(i.offset);
auto ops = stream(i);
auto op = static_cast<Op>(i.op);
switch (op)
@ -119,7 +119,7 @@ void Compiler::register_global_read_dependencies(const SPIRBlock &block, uint32_
{
for (auto &i : block.ops)
{
auto ops = stream(i.offset);
auto ops = stream(i);
auto op = static_cast<Op>(i.op);
switch (op)
@ -443,11 +443,11 @@ static string extract_string(const vector<uint32_t> &spirv, uint32_t offset)
void Compiler::parse()
{
auto len = spirv.size();
auto s = stream(0);
if (len < 5)
throw CompilerError("SPIRV file too small.");
auto s = spirv.data();
// Endian-swap if we need to.
if (s[0] == swap_endian(MagicNumber))
transform(begin(spirv), end(spirv), begin(spirv), [](uint32_t c) { return swap_endian(c); });
@ -778,7 +778,7 @@ void Compiler::unset_decoration(uint32_t id, Decoration decoration)
void Compiler::parse(const Instruction &i)
{
auto ops = stream(i.offset);
auto ops = stream(i);
auto op = static_cast<Op>(i.op);
uint32_t length = i.length;
@ -1651,7 +1651,7 @@ bool Compiler::traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHand
// inside dead blocks ...
for (auto &i : block.ops)
{
auto ops = stream(i.offset);
auto ops = stream(i);
auto op = static_cast<Op>(i.op);
if (!handler.handle(op, ops, i.length))

View File

@ -168,11 +168,17 @@ namespace spirv_cross
ShaderResources get_shader_resources() const;
protected:
const uint32_t* stream(uint32_t offset) const
const uint32_t* stream(const Instruction &instr) const
{
if (offset > spirv.size())
// If we're not going to use any arguments, just return nullptr.
// We want to avoid case where we return an out of range pointer
// that trips debug assertions on some platforms.
if (!instr.length)
return nullptr;
if (instr.offset + instr.length > spirv.size())
throw CompilerError("Compiler::stream() out of range.");
return &spirv[offset];
return &spirv[instr.offset];
}
std::vector<uint32_t> spirv;

View File

@ -1353,7 +1353,7 @@ void CompilerGLSL::emit_mix_op(uint32_t result_type, uint32_t id,
void CompilerGLSL::emit_texture_op(const Instruction &i)
{
auto ops = stream(i.offset);
auto ops = stream(i);
auto op = static_cast<Op>(i.op);
uint32_t length = i.length;
@ -2274,7 +2274,7 @@ string CompilerGLSL::build_composite_combiner(const uint32_t *elems, uint32_t le
void CompilerGLSL::emit_instruction(const Instruction &i)
{
auto ops = stream(i.offset);
auto ops = stream(i);
auto op = static_cast<Op>(i.op);
uint32_t length = i.length;
@ -3615,7 +3615,7 @@ void CompilerGLSL::emit_function(SPIRFunction &func, uint64_t return_flags)
auto &b = get<SPIRBlock>(block);
for (auto &i : b.ops)
{
auto ops = stream(i.offset);
auto ops = stream(i);
auto op = static_cast<Op>(i.op);
if (op == OpFunctionCall)