Fix crash when comparing against a negated constant vector.

This CL solves the fuzzer crash. Constant propagation of the negative
sign into the vector will be investigated in a followup CL.

This CL also adds a few cleanups into IRGenerator::constantFold.

Change-Id: If73a4fe2a5777265e7d43cc4f482653a38cb59af
Bug: oss-fuzz:26830, oss-fuzz:26789
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/332261
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
John Stiles 2020-11-04 16:23:26 -05:00 committed by Skia Commit-Bot
parent 6c88ea1278
commit 95acbbc3c9
3 changed files with 47 additions and 26 deletions

View File

@ -1726,9 +1726,9 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
const Expression& right) const {
// If the left side is a constant boolean literal, the right side does not need to be constant
// for short circuit optimizations to allow the constant to be folded.
if (left.kind() == Expression::Kind::kBoolLiteral && !right.isCompileTimeConstant()) {
if (left.is<BoolLiteral>() && !right.isCompileTimeConstant()) {
return short_circuit_boolean(fContext, left, op, right);
} else if (right.kind() == Expression::Kind::kBoolLiteral && !left.isCompileTimeConstant()) {
} else if (right.is<BoolLiteral>() && !left.isCompileTimeConstant()) {
// There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
// (right OP left) for short-circuit optimizations
return short_circuit_boolean(fContext, right, op, left);
@ -1742,8 +1742,7 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
// precision to calculate the results and hope the result makes sense. The plan is to move the
// Skia caps into SkSL, so we have access to all of them including the precisions of the various
// types, which will let us be more intelligent about this.
if (left.kind() == Expression::Kind::kBoolLiteral &&
right.kind() == Expression::Kind::kBoolLiteral) {
if (left.is<BoolLiteral>() && right.is<BoolLiteral>()) {
bool leftVal = left.as<BoolLiteral>().value();
bool rightVal = right.as<BoolLiteral>().value();
bool result;
@ -1753,15 +1752,14 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
case Token::Kind::TK_LOGICALXOR: result = leftVal ^ rightVal; break;
default: return nullptr;
}
return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
return std::make_unique<BoolLiteral>(fContext, left.fOffset, result);
}
#define RESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
leftVal op rightVal)
#define URESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
(uint32_t) leftVal op \
(uint32_t) rightVal)
if (left.kind() == Expression::Kind::kIntLiteral &&
right.kind() == Expression::Kind::kIntLiteral) {
if (left.is<IntLiteral>() && right.is<IntLiteral>()) {
int64_t leftVal = left.as<IntLiteral>().value();
int64_t rightVal = right.as<IntLiteral>().value();
switch (op) {
@ -1814,8 +1812,7 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
return nullptr;
}
}
if (left.kind() == Expression::Kind::kFloatLiteral &&
right.kind() == Expression::Kind::kFloatLiteral) {
if (left.is<FloatLiteral>() && right.is<FloatLiteral>()) {
SKSL_FLOAT leftVal = left.as<FloatLiteral>().value();
SKSL_FLOAT rightVal = right.as<FloatLiteral>().value();
switch (op) {
@ -1842,19 +1839,25 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
if (leftType.typeKind() == Type::TypeKind::kVector && leftType.componentType().isFloat() &&
leftType == rightType) {
ExpressionArray args;
#define RETURN_VEC_COMPONENTWISE_RESULT(op) \
for (int i = 0; i < leftType.columns(); i++) { \
SKSL_FLOAT value = left.getFVecComponent(i) op right.getFVecComponent(i); \
args.push_back(std::make_unique<FloatLiteral>(fContext, /*offset=*/-1, value)); \
} \
return std::make_unique<Constructor>(/*offset=*/-1, &leftType, std::move(args))
#define RETURN_VEC_COMPONENTWISE_RESULT(op) \
for (int i = 0; i < leftType.columns(); i++) { \
SKSL_FLOAT value = left.getFVecComponent(i) op right.getFVecComponent(i); \
args.push_back(std::make_unique<FloatLiteral>(fContext, left.fOffset, value)); \
} \
return std::make_unique<Constructor>(left.fOffset, &leftType, std::move(args))
switch (op) {
case Token::Kind::TK_EQEQ:
return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
left.compareConstant(fContext, right)));
if (left.kind() == right.kind()) {
return std::make_unique<BoolLiteral>(fContext, left.fOffset,
left.compareConstant(fContext, right));
}
return nullptr;
case Token::Kind::TK_NEQ:
return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
!left.compareConstant(fContext, right)));
if (left.kind() == right.kind()) {
return std::make_unique<BoolLiteral>(fContext, left.fOffset,
!left.compareConstant(fContext, right));
}
return nullptr;
case Token::Kind::TK_PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
case Token::Kind::TK_MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
case Token::Kind::TK_STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
@ -1872,16 +1875,17 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
default:
return nullptr;
}
#undef RETURN_VEC_COMPONENTWISE_RESULT
}
if (leftType.typeKind() == Type::TypeKind::kMatrix &&
rightType.typeKind() == Type::TypeKind::kMatrix &&
left.kind() == right.kind()) {
switch (op) {
case Token::Kind::TK_EQEQ:
return std::make_unique<BoolLiteral>(fContext, /*offset=*/-1,
return std::make_unique<BoolLiteral>(fContext, left.fOffset,
left.compareConstant(fContext, right));
case Token::Kind::TK_NEQ:
return std::make_unique<BoolLiteral>(fContext, /*offset=*/-1,
return std::make_unique<BoolLiteral>(fContext, left.fOffset,
!left.compareConstant(fContext, right));
default:
return nullptr;

View File

@ -1,3 +1,7 @@
### Compilation failed:
out vec4 sk_FragColor;
void main() {
sk_FragColor.x = 1.0;
sk_FragColor.y = float(vec4(1.0) == -vec4(1.0) ? 1 : 0);
sk_FragColor.z = float(vec4(0.0) == -vec4(0.0) ? 1 : 0);
}

View File

@ -1,3 +1,16 @@
### Compilation failed:
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct Inputs {
};
struct Outputs {
float4 sk_FragColor [[color(0)]];
};
fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
Outputs _outputStruct;
thread Outputs* _out = &_outputStruct;
_out->sk_FragColor.x = 1.0;
_out->sk_FragColor.y = float(all(float4(1.0) == -float4(1.0)) ? 1 : 0);
_out->sk_FragColor.z = float(all(float4(0.0) == -float4(0.0)) ? 1 : 0);
return *_out;
}