diff --git a/tools/packaging/verify-linux-frame-copy-runtime.mjs b/tools/packaging/verify-linux-frame-copy-runtime.mjs index 5b562c747..de6b9c082 100644 --- a/tools/packaging/verify-linux-frame-copy-runtime.mjs +++ b/tools/packaging/verify-linux-frame-copy-runtime.mjs @@ -546,6 +546,21 @@ export function validateExtractedSnapMetadata(extractionRoot) { } const plugEntries = directYamlMappingEntries(lines, plugs, 2); + if ( + !plugEntries || + plugEntries.some(({ value }) => value.length > 0) + ) { + errors.push( + 'Extracted Snap plug declarations must use block mappings.' + ); + } + if ( + plugEntries && + new Set(plugEntries.map(({ key }) => key)).size !== + plugEntries.length + ) { + errors.push('Extracted Snap direct plug keys must be unique.'); + } const sharedMemoryInterfaces = plugEntries?.filter((plugEntry) => { const plugFields = directYamlMappingEntries( @@ -582,12 +597,18 @@ export function validateExtractedSnapMetadata(extractionRoot) { lines.length ); let hasSharedMemorySlot = slotsEntries.length > 1; + let invalidSlotsShape = slotsEntries.some( + ({ value }) => value.length > 0 + ); for (const slots of slotsEntries) { const slotEntries = directYamlMappingEntries(lines, slots, 2); if (!slotEntries) { - hasSharedMemorySlot = true; + invalidSlotsShape = true; continue; } + invalidSlotsShape ||= slotEntries.some( + ({ value }) => value.length > 0 + ); hasSharedMemorySlot ||= slotEntries.some((slotEntry) => { if (slotEntry.key === 'shared-memory') { return true; @@ -602,6 +623,11 @@ export function validateExtractedSnapMetadata(extractionRoot) { ); }); } + if (invalidSlotsShape) { + errors.push( + 'Extracted Snap slots must use block mappings with scalar fields.' + ); + } if (hasSharedMemorySlot) { errors.push( 'Extracted Snap metadata must not declare a shared-memory slot.' diff --git a/tools/packaging/verify-linux-frame-copy-runtime.test.mjs b/tools/packaging/verify-linux-frame-copy-runtime.test.mjs index 35bf05bf7..96e1a0228 100644 --- a/tools/packaging/verify-linux-frame-copy-runtime.test.mjs +++ b/tools/packaging/verify-linux-frame-copy-runtime.test.mjs @@ -639,6 +639,27 @@ test('requires a private top-level shared-memory plug used by the Snap app', () `${contents}slots:\n shared-memory:\n interface: shared-memory\n`, /must not declare.*shared-memory slot/i, ], + [ + (contents) => + contents.replace( + '\nplugs:\n', + '\nplugs:\n other: { interface: shared-memory }\n' + ), + /plug declarations.*block mappings/i, + ], + [ + (contents) => + `${contents}slots: { leak: { interface: shared-memory } }\n`, + /slots.*block mappings/i, + ], + [ + (contents) => + contents.replace( + '\nplugs:\n', + '\nplugs:\n network:\n interface: network\n network:\n interface: network\n' + ), + /plug keys.*unique/i, + ], [ (contents) => contents.replace(