fix(recompiler): reject a stored plan whose image table names a missing source
DecodePlan checked every descriptor source index a plan holds except the two inside an indirect image table: the heap source and the material source. A damaged entry could therefore decode with a table that points past the plan's descriptor sources, and only the materializer's own bounds checks stood between it and an out-of-range read. The front end interns both sources before the image source that names them, so a plan it builds always passes the new check. agc_shader_disk_cache now requires a plan whose table heap or material source lies past the sources not to decode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1ed6c21067
commit
ed3f2776ed
|
|
@ -1455,6 +1455,8 @@ void verifyMalformedPlans() {
|
|||
rejects("an image past the sources", [](IrResourcePlan& plan) { plan.info.images[0].source = 5u; });
|
||||
rejects("a descriptor of nine dwords", [](IrResourcePlan& plan) { plan.descriptorSources[1].dwordCount = 9u; });
|
||||
rejects("a uniform fill of five words", [](IrResourcePlan& plan) { plan.uniformFill.fill.words = 5u; });
|
||||
rejects("an image table heap past the sources", [](IrResourcePlan& plan) { plan.descriptorSources[1].indirectImage->heapSource = 4u; });
|
||||
rejects("an image table material past the sources", [](IrResourcePlan& plan) { plan.descriptorSources[1].indirectImage->materialSource = 4u; });
|
||||
auto foreign = handBuiltPlan();
|
||||
IrValue stray(IrOpcode::Void, IrType::U32, 99u);
|
||||
foreign.srtReads[0].value = &stray;
|
||||
|
|
|
|||
|
|
@ -1029,7 +1029,7 @@ bool decodePlan(Reader& reader, IrResourcePlan& plan) {
|
|||
if (!valid || !reader.Done() || fill.words > plan.uniformFill.values.size()) return false;
|
||||
const auto knownSource = [&](std::uint32_t source) { return source < plan.descriptorSources.size(); };
|
||||
if (!std::ranges::all_of(plan.materializationSources, knownSource)) return false;
|
||||
if (!std::ranges::all_of(plan.descriptorSources, [](const DescriptorSource& source) { return source.dwordCount <= source.dwords.size(); })) return false;
|
||||
if (!std::ranges::all_of(plan.descriptorSources, [&](const DescriptorSource& source) { return source.dwordCount <= source.dwords.size() && (!source.indirectImage.has_value() || (knownSource(source.indirectImage->heapSource) && knownSource(source.indirectImage->materialSource))); })) return false;
|
||||
if (!std::ranges::all_of(plan.info.buffers, [&](const BufferResource& buffer) { return knownSource(buffer.source); })) return false;
|
||||
if (!std::ranges::all_of(plan.info.images, [&](const ImageResource& image) { return knownSource(image.source); })) return false;
|
||||
if (!std::ranges::all_of(plan.info.samplers, [&](const SamplerResource& sampler) { return knownSource(sampler.source); })) return false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue