reader/spirv: Prevent nullptrs being passed to ast::CallExpression.

nullptrs are caused by errors. Detect and return before passing nullptrs to places they shouldn't go.

Also: Rename 'params' to 'args'. These are arguments, not parameters.

Bug: oss-fuzz:38074
Fixed: tint:1355
Change-Id: I77f97b4a8e5dab21802b300ba3eedad767ac2ad5
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/75425
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2022-01-05 20:11:41 +00:00 committed by Tint LUCI CQ
parent 5c99ed046a
commit 4a143a40a3
1 changed files with 21 additions and 15 deletions

View File

@ -5207,7 +5207,7 @@ const ast::Expression* FunctionEmitter::GetSamplerExpression(
} }
bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) { bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
ast::ExpressionList params; ast::ExpressionList args;
const auto opcode = inst.opcode(); const auto opcode = inst.opcode();
// Form the texture operand. // Form the texture operand.
@ -5215,13 +5215,13 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
if (!image) { if (!image) {
return false; return false;
} }
params.push_back(GetImageExpression(inst)); args.push_back(GetImageExpression(inst));
// Form the sampler operand, if needed. // Form the sampler operand, if needed.
if (IsSampledImageAccess(opcode)) { if (IsSampledImageAccess(opcode)) {
// Form the sampler operand. // Form the sampler operand.
if (auto* sampler = GetSamplerExpression(inst)) { if (auto* sampler = GetSamplerExpression(inst)) {
params.push_back(sampler); args.push_back(sampler);
} else { } else {
return false; return false;
} }
@ -5247,7 +5247,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
if (coords.empty()) { if (coords.empty()) {
return false; return false;
} }
params.insert(params.end(), coords.begin(), coords.end()); args.insert(args.end(), coords.begin(), coords.end());
// Skip the coordinates operand. // Skip the coordinates operand.
arg_index++; arg_index++;
@ -5257,7 +5257,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
// the parameter list. Issues a diagnostic and returns false on error. // the parameter list. Issues a diagnostic and returns false on error.
auto consume_dref = [&]() -> bool { auto consume_dref = [&]() -> bool {
if (arg_index < num_args) { if (arg_index < num_args) {
params.push_back(MakeOperand(inst, arg_index).expr); args.push_back(MakeOperand(inst, arg_index).expr);
arg_index++; arg_index++;
} else { } else {
return Fail() return Fail()
@ -5295,7 +5295,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
builtin_name = "textureGather"; builtin_name = "textureGather";
if (!texture_type->Is<DepthTexture>()) { if (!texture_type->Is<DepthTexture>()) {
// The explicit component is the *first* argument in WGSL. // The explicit component is the *first* argument in WGSL.
params.insert(params.begin(), ToI32(MakeOperand(inst, arg_index)).expr); args.insert(args.begin(), ToI32(MakeOperand(inst, arg_index)).expr);
} }
// Skip over the component operand, even for depth textures. // Skip over the component operand, even for depth textures.
arg_index++; arg_index++;
@ -5324,7 +5324,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
return false; return false;
} }
params.push_back(converted_texel); args.push_back(converted_texel);
arg_index++; arg_index++;
} else { } else {
return Fail() << "image write is missing a Texel operand: " return Fail() << "image write is missing a Texel operand: "
@ -5356,7 +5356,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
<< inst.PrettyPrint(); << inst.PrettyPrint();
} }
builtin_name += "Bias"; builtin_name += "Bias";
params.push_back(MakeOperand(inst, arg_index).expr); args.push_back(MakeOperand(inst, arg_index).expr);
image_operands_mask ^= SpvImageOperandsBiasMask; image_operands_mask ^= SpvImageOperandsBiasMask;
arg_index++; arg_index++;
} }
@ -5383,7 +5383,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
// Convert it to a signed integer type. // Convert it to a signed integer type.
lod = ToI32(lod); lod = ToI32(lod);
} }
params.push_back(lod.expr); args.push_back(lod.expr);
} }
image_operands_mask ^= SpvImageOperandsLodMask; image_operands_mask ^= SpvImageOperandsLodMask;
@ -5393,7 +5393,7 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
->IsAnyOf<DepthMultisampledTexture, MultisampledTexture>()) { ->IsAnyOf<DepthMultisampledTexture, MultisampledTexture>()) {
// textureLoad requires an explicit level-of-detail parameter for // textureLoad requires an explicit level-of-detail parameter for
// non-multisampled texture types. // non-multisampled texture types.
params.push_back(parser_impl_.MakeNullValue(ty_.I32())); args.push_back(parser_impl_.MakeNullValue(ty_.I32()));
} }
if (arg_index + 1 < num_args && if (arg_index + 1 < num_args &&
(image_operands_mask & SpvImageOperandsGradMask)) { (image_operands_mask & SpvImageOperandsGradMask)) {
@ -5408,8 +5408,8 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
<< inst.PrettyPrint(); << inst.PrettyPrint();
} }
builtin_name += "Grad"; builtin_name += "Grad";
params.push_back(MakeOperand(inst, arg_index).expr); args.push_back(MakeOperand(inst, arg_index).expr);
params.push_back(MakeOperand(inst, arg_index + 1).expr); args.push_back(MakeOperand(inst, arg_index + 1).expr);
image_operands_mask ^= SpvImageOperandsGradMask; image_operands_mask ^= SpvImageOperandsGradMask;
arg_index += 2; arg_index += 2;
} }
@ -5431,14 +5431,14 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
<< inst.PrettyPrint(); << inst.PrettyPrint();
} }
params.push_back(ToSignedIfUnsigned(MakeOperand(inst, arg_index)).expr); args.push_back(ToSignedIfUnsigned(MakeOperand(inst, arg_index)).expr);
image_operands_mask ^= SpvImageOperandsConstOffsetMask; image_operands_mask ^= SpvImageOperandsConstOffsetMask;
arg_index++; arg_index++;
} }
if (arg_index < num_args && if (arg_index < num_args &&
(image_operands_mask & SpvImageOperandsSampleMask)) { (image_operands_mask & SpvImageOperandsSampleMask)) {
// TODO(dneto): only permitted with ImageFetch // TODO(dneto): only permitted with ImageFetch
params.push_back(ToI32(MakeOperand(inst, arg_index)).expr); args.push_back(ToI32(MakeOperand(inst, arg_index)).expr);
image_operands_mask ^= SpvImageOperandsSampleMask; image_operands_mask ^= SpvImageOperandsSampleMask;
arg_index++; arg_index++;
} }
@ -5447,10 +5447,16 @@ bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
<< "): " << inst.PrettyPrint(); << "): " << inst.PrettyPrint();
} }
// If any of the arguments are nullptr, then we've failed.
if (std::any_of(args.begin(), args.end(),
[](auto* expr) { return expr == nullptr; })) {
return false;
}
auto* ident = create<ast::IdentifierExpression>( auto* ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register(builtin_name)); Source{}, builder_.Symbols().Register(builtin_name));
auto* call_expr = auto* call_expr =
create<ast::CallExpression>(Source{}, ident, std::move(params)); create<ast::CallExpression>(Source{}, ident, std::move(args));
if (inst.type_id() != 0) { if (inst.type_id() != 0) {
// It returns a value. // It returns a value.