@@ -2813,8 +2813,8 @@ def _arg_shown(a):
28132813 ['Wipe Device confirm' , 'Import Recovery Sentence confirm' ,
28142814 'Home screen while locked out by the bitcoin-only band: no wallet' ,
28152815 'Bitcoin Account #0 / Address #0 after the band stamp is removed - the wallet is back' ]),
2816- ('U5' , 'test_storage_version_gate' , 'test_active_flash_format_is_v20 ' ,
2817- 'This build writes flash format V20, and the bump is argued ' ,
2816+ ('U5' , 'test_storage_version_gate' , 'test_last_shipped_never_moves_backwards ' ,
2817+ 'STORAGE_VERSION_LAST_SHIPPED never moves backwards ' ,
28182818 'An independent witness for the number the whole gate turns on. The compile-time '
28192819 'assert in storage.c compares STORAGE_VERSION against STORAGE_VERSION_LAST_SHIPPED - '
28202820 'two values in the same header, editable in one commit - so it cannot notice a release '
@@ -2831,11 +2831,18 @@ def _arg_shown(a):
28312831 'which is normal downgrade behaviour and is in the release note rather than left to be '
28322832 'discovered.' ,
28332833 []),
2834- ('U5b' , 'test_storage_version_gate' , 'test_burned_versions_have_no_reader' ,
2835- 'Formats 18 and 19 have no reader, on purpose' ,
2836- 'The absence of a dispatch case is what sends a burned blob to the wipe path. That is '
2837- 'an easy thing to undo while tidying a switch statement, and undoing it would silently '
2838- 'restore the misparse - so the absence is asserted rather than assumed.' ,
2834+ ('U5b' , 'test_storage_version_gate' ,
2835+ 'test_burned_versions_are_dispatched_to_the_wipe_path' ,
2836+ 'A burned format is dispatched, and what it reaches is the wipe' ,
2837+ 'This used to assert the ABSENCE of a dispatch case, on the theory that a burned blob '
2838+ 'falls through to a default. It does not: storage_fromFlash() has no default case, '
2839+ 'deliberately, so that -Werror=switch names any version nobody handled. An unlisted '
2840+ 'version therefore does not fall anywhere - it fails the ARM build. So the label must '
2841+ 'exist; what must NOT exist is a reader behind it. Asserted as the real property: the '
2842+ 'burned versions are dispatched, and the arm they reach returns SUS_Invalid with no '
2843+ 'storage_readVxx call. Which versions are burned is read from '
2844+ 'storage_versions.inc rather than written down here, so the test holds on a line that '
2845+ 'burns nothing as readily as on one that burns two.' ,
28392846 []),
28402847 ('U6' , 'test_storage_version_gate' , 'test_version_never_drops_below_a_shipped_release' ,
28412848 'The version never goes backwards or into the band' ,
@@ -2854,13 +2861,15 @@ def _arg_shown(a):
28542861 'contiguous from 1 and that its last entry is STORAGE_VERSION - the two properties the '
28552862 'in-tree static asserts depend on.' ,
28562863 []),
2857- ('U8' , 'test_storage_version_gate' , 'test_every_ladder_version_has_a_reader ' ,
2858- 'Every ladder version has a reader case ' ,
2864+ ('U8' , 'test_storage_version_gate' , 'test_every_shipped_version_has_a_reader ' ,
2865+ 'Every shipped version still has a reader' ,
28592866 'The failure the static asserts do NOT cover. They pin the enum to its own numbering '
2860- 'and say nothing about the switch in storage_fromFlash(). Drop a case and control '
2861- 'falls out of the switch to return SUS_Invalid, which storage_init() answers with '
2862- 'storage_reset() - every device carrying that version is wiped on upgrade and the '
2863- 'build stays green.' ,
2867+ 'and say nothing about what the switch in storage_fromFlash() does with it. Drop the '
2868+ 'reader for a version that reached hardware and every device carrying it is wiped on '
2869+ 'upgrade. Scoped to SHIPPED versions on purpose: a burned format legitimately has no '
2870+ 'reader, so asserting "every ladder version has a reader" would make burning one '
2871+ 'impossible to express. The companion assertion, that no shipped version is ever '
2872+ 'declared burned, is what stops that scoping being used as a loophole.' ,
28642873 []),
28652874 ]),
28662875
0 commit comments