Reject unsupported parsed PPI blend modes

This commit is contained in:
2026-06-02 17:39:45 +02:00
parent 52da64fc96
commit 48fdfd849d
4 changed files with 14 additions and 2 deletions

View File

@@ -92,7 +92,7 @@ Known local toolchain state:
`pp_paint_renderer`, `pp_paint_renderer`,
`pp_ui_core`, `pano_cli`, and their current headless test binaries, `pp_ui_core`, `pano_cli`, and their current headless test binaries,
including foundation binary-stream/event/logging/task queue coverage, PNG metadata and including foundation binary-stream/event/logging/task queue coverage, PNG metadata and
decode, PPI header/layout/non-finite opacity rejection, settings document, document decode, PPI header/layout/non-finite opacity and blend-mode rejection, settings document, document
snapshot/per-layer-frame/move/duration/face-pixel/PPI export coverage, snapshot/per-layer-frame/move/duration/face-pixel/PPI export coverage,
snapshot-embedded face-payload rejection, paint brush/final-blend/ snapshot-embedded face-payload rejection, paint brush/final-blend/
stroke-alpha-blend/stroke spacing/stroke stress/stroke-script coverage, stroke-alpha-blend/stroke spacing/stroke stress/stroke-script coverage,

View File

@@ -316,7 +316,8 @@ PNG IHDR metadata parsing, PPI header/project byte-layout/body-summary
recognition, layer/frame indexing, dirty-face PNG payload metadata validation, recognition, layer/frame indexing, dirty-face PNG payload metadata validation,
asset-level RGBA PNG payload decoding, and a pure typed settings document asset-level RGBA PNG payload decoding, and a pure typed settings document
model, with model, with
corrupt/truncated/unsupported, non-finite opacity, extreme-dimension, and key/value limit tests. corrupt/truncated/unsupported, non-finite opacity, unsupported blend-mode,
extreme-dimension, and key/value limit tests.
`pp_paint` has started with pure brush parameter validation/stamp evaluation, `pp_paint` has started with pure brush parameter validation/stamp evaluation,
CPU reference math for the five current final RGBA shader blend modes plus the CPU reference math for the five current final RGBA shader blend modes plus the
shader-style stroke-alpha blend modes used by pattern/dual-brush mixing, and deterministic shader-style stroke-alpha blend modes used by pattern/dual-brush mixing, and deterministic

View File

@@ -383,6 +383,11 @@ pp::foundation::Result<PpiBodySummary> parse_ppi_body_impl(
pp::foundation::Status::invalid_argument("PPI layer boolean field is invalid")); pp::foundation::Status::invalid_argument("PPI layer boolean field is invalid"));
} }
if (blend_mode.value() > 4U) {
return pp::foundation::Result<PpiBodySummary>::failure(
pp::foundation::Status::out_of_range("PPI layer blend mode is outside the supported range"));
}
if (index != nullptr) { if (index != nullptr) {
layer_summary.blend_mode = blend_mode.value(); layer_summary.blend_mode = blend_mode.value();
layer_summary.alpha_locked = alpha_locked.value() != 0U; layer_summary.alpha_locked = alpha_locked.value() != 0U;

View File

@@ -395,10 +395,14 @@ void rejects_invalid_project_body_summaries(pp::tests::Harness& h)
ppi_header_size + (128U * 128U * 4U) + 20U, ppi_header_size + (128U * 128U * 4U) + 20U,
std::numeric_limits<float>::quiet_NaN()); std::numeric_limits<float>::quiet_NaN());
auto bad_blend_mode = minimal_project();
write_u32_at(bad_blend_mode, ppi_header_size + (128U * 128U * 4U) + 31U, 99U);
const auto truncated_result = parse_ppi_project_summary(truncated); const auto truncated_result = parse_ppi_project_summary(truncated);
const auto mismatched_frames_result = parse_ppi_project_summary(mismatched_frames); const auto mismatched_frames_result = parse_ppi_project_summary(mismatched_frames);
const auto bad_layer_name_result = parse_ppi_project_summary(bad_layer_name); const auto bad_layer_name_result = parse_ppi_project_summary(bad_layer_name);
const auto non_finite_opacity_result = parse_ppi_project_summary(non_finite_opacity); const auto non_finite_opacity_result = parse_ppi_project_summary(non_finite_opacity);
const auto bad_blend_mode_result = parse_ppi_project_summary(bad_blend_mode);
PP_EXPECT(h, !truncated_result.ok()); PP_EXPECT(h, !truncated_result.ok());
PP_EXPECT(h, truncated_result.status().code == StatusCode::out_of_range); PP_EXPECT(h, truncated_result.status().code == StatusCode::out_of_range);
@@ -408,6 +412,8 @@ void rejects_invalid_project_body_summaries(pp::tests::Harness& h)
PP_EXPECT(h, bad_layer_name_result.status().code == StatusCode::out_of_range); PP_EXPECT(h, bad_layer_name_result.status().code == StatusCode::out_of_range);
PP_EXPECT(h, !non_finite_opacity_result.ok()); PP_EXPECT(h, !non_finite_opacity_result.ok());
PP_EXPECT(h, non_finite_opacity_result.status().code == StatusCode::invalid_argument); PP_EXPECT(h, non_finite_opacity_result.status().code == StatusCode::invalid_argument);
PP_EXPECT(h, !bad_blend_mode_result.ok());
PP_EXPECT(h, bad_blend_mode_result.status().code == StatusCode::out_of_range);
} }
void creates_minimal_project_for_roundtrip_load(pp::tests::Harness& h) void creates_minimal_project_for_roundtrip_load(pp::tests::Harness& h)