Check for shader data validity and add tests (flutter/engine#34793)

This commit is contained in:
Zachary Anderson 2022-07-20 18:45:11 -07:00 committed by GitHub
parent 131f0a3555
commit 69f22945ed
5 changed files with 45 additions and 15 deletions

View File

@ -65,9 +65,6 @@ RuntimeStage::RuntimeStage(std::shared_ptr<fml::Mapping> payload)
return;
}
if (!fb::RuntimeStageBufferHasIdentifier(payload_->GetMapping())) {
VALIDATION_LOG
<< "Impeller Runtime stage has invalid magic. Perhaps the stage "
"information is for the incorrect backend or the data is corrupted?";
return;
}
auto runtime_stage = fb::GetRuntimeStage(payload_->GetMapping());

View File

@ -4126,7 +4126,10 @@ class FragmentProgram extends NativeFieldWrapperClass1 {
@pragma('vm:entry-point')
FragmentProgram._fromAsset(String assetKey) {
_constructor();
_initFromAsset(assetKey);
final String result = _initFromAsset(assetKey);
if (result.isNotEmpty) {
throw result;
}
}
static void _reinitializeShader(String assetKey) {
@ -4145,7 +4148,10 @@ class FragmentProgram extends NativeFieldWrapperClass1 {
return;
}
program._initFromAsset(assetKey);
final result = program._initFromAsset(assetKey);
if (result.isNotEmpty) {
throw result;
}
}
late final int _uniformFloatCount;
@ -4157,8 +4163,8 @@ class FragmentProgram extends NativeFieldWrapperClass1 {
@FfiNative<Void Function(Pointer<Void>, Handle, Bool)>('FragmentProgram::init')
external void _init(String sksl, bool debugPrint);
@FfiNative<Void Function(Pointer<Void>, Handle)>('FragmentProgram::initFromAsset')
external void _initFromAsset(String assetKey);
@FfiNative<Handle Function(Pointer<Void>, Handle)>('FragmentProgram::initFromAsset')
external String _initFromAsset(String assetKey);
/// Constructs a [Shader] object suitable for use by [Paint.shader] with
/// the given uniforms.

View File

@ -22,18 +22,21 @@ namespace flutter {
IMPLEMENT_WRAPPERTYPEINFO(ui, FragmentProgram);
void FragmentProgram::initFromAsset(std::string asset_name) {
std::string FragmentProgram::initFromAsset(std::string asset_name) {
std::shared_ptr<AssetManager> asset_manager = UIDartState::Current()
->platform_configuration()
->client()
->GetAssetManager();
std::unique_ptr<fml::Mapping> data = asset_manager->GetAsMapping(asset_name);
if (data == nullptr) {
Dart_ThrowException(tonic::ToDart("Asset '" + asset_name + "' not found"));
return;
return std::string("Asset '") + asset_name + std::string("' not found");
}
auto runtime_stage = impeller::RuntimeStage(std::move(data));
if (!runtime_stage.IsValid()) {
return std::string("Asset '") + asset_name +
std::string("' does not contain valid shader data.");
}
{
auto code_mapping = runtime_stage.GetCodeMapping();
auto code_size = code_mapping->GetSize();
@ -43,10 +46,8 @@ void FragmentProgram::initFromAsset(std::string asset_name) {
SkRuntimeEffect::Result result =
SkRuntimeEffect::MakeForShader(SkString(sksl, code_size));
if (result.effect == nullptr) {
Dart_ThrowException(tonic::ToDart(std::string("Invalid SkSL:\n") + sksl +
std::string("\nSkSL Error:\n") +
result.errorText.c_str()));
return;
return std::string("Invalid SkSL:\n") + sksl +
std::string("\nSkSL Error:\n") + result.errorText.c_str();
}
runtime_effect_ = result.effect;
}
@ -84,6 +85,8 @@ void FragmentProgram::initFromAsset(std::string asset_name) {
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
return "";
}
void FragmentProgram::init(std::string sksl, bool debugPrintSksl) {

View File

@ -24,7 +24,7 @@ class FragmentProgram : public RefCountedDartWrappable<FragmentProgram> {
~FragmentProgram() override;
static void Create(Dart_Handle wrapper);
void initFromAsset(std::string asset_name);
std::string initFromAsset(std::string asset_name);
void init(std::string sksl, bool debugPrintSksl);

View File

@ -295,6 +295,30 @@ void main() {
await _expectShaderRendersGreen(shader);
});
test('iplr throws an exception on invalid assetKey', () async {
bool throws = false;
try {
final FragmentProgram program = FragmentProgram.fromAsset(
'<invalid>',
);
} catch (e) {
throws = true;
}
expect(throws, equals(true));
});
test('iplr throws an exception on invalid data', () async {
bool throws = false;
try {
final FragmentProgram program = FragmentProgram.fromAsset(
'DashInNooglerHat.jpg',
);
} catch (e) {
throws = true;
}
expect(throws, equals(true));
});
// Test all supported GLSL ops. See lib/spirv/lib/src/constants.dart
final Map<String, ByteBuffer> supportedGLSLOpShaders = _loadShaders(
path.join('supported_glsl_op_shaders', 'spirv'),