Timeline: safeguard agains injecting a poisonous metric factor

This commit is contained in:
Fischlurch 2022-11-26 19:45:10 +01:00
parent 90aba4df09
commit b898f1514b
3 changed files with 157 additions and 15 deletions

View file

@ -171,7 +171,7 @@ namespace model {
/** Maximum quantiser to be handled in fractional arithmetics without hazard.
* @remark due to the common divisor normalisation, and the typical time computations,
* DENOMINATOR * Time::Scale has to stay below INT_MAX, with some safety margin
* DENOMINATOR * Time::Scale has to stay below INT_MAX, with some safety margin
*/
const int64_t LIM_HAZARD{int64_t{1} << 40 };
@ -527,9 +527,9 @@ namespace model {
REQUIRE (pxWidth > 0);
REQUIRE (afterWin_> startWin_);
FSecs dur{afterWin_-startWin_};
Rat adjMetric = Rat(pxWidth) / dur;
Rat adjMetric = detox (Rat(pxWidth) / dur);
ENSURE (pxWidth == rational_cast<uint> (adjMetric*dur));
return detox (adjMetric);
return adjMetric;
}
void
@ -541,7 +541,8 @@ namespace model {
uint pxWidth = rational_cast<uint> (px_per_sec_*dur);
dur = Rat(pxWidth) / detox (changedMetric);
dur = min (dur, MAX_TIMESPAN);
dur = max (dur, MICRO_TICK); // prevent window going void
dur = max (dur, MICRO_TICK); // prevent window going void
dur = detox (dur); // prevent integer wrap in time conversion
TimeVar timeDur{dur};
// prefer bias towards increased window instead of increased metric
if (not isMicroGridAligned (dur))
@ -673,7 +674,7 @@ namespace model {
void
mutateScale (Rat changedMetric)
{
changedMetric = min (changedMetric, ZOOM_MAX_RESOLUTION);
changedMetric = min (detox(changedMetric), ZOOM_MAX_RESOLUTION);
if (changedMetric == px_per_sec_) return;
uint px{pxWidth()};
@ -687,7 +688,7 @@ namespace model {
px_per_sec_ = conformMetricToWindow(px);
}
else
mutateDuration (dur);
mutateDuration (dur, px);
ensureInvariants (px);
}

View file

@ -90,6 +90,10 @@ namespace test {
safeguard_zero_init();
safeguard_reversed_intervals();
safeguard_toxic_zoomFactor();
safeguard_poisonousMetric();
safeguard_extremeZoomOut();
safeguard_extremeTimePos();
safeguard_extremeOffset();
}
@ -546,6 +550,7 @@ namespace test {
{
Rat poison{_raw(Time::MAX)-101010101010101010, _raw(Time::MAX)+23};
CHECK (poison == 206435633551724850_r/307445734561825883);
CHECK (2_r/3 < poison and poison < 1); // looks innocuous...
CHECK (poison + Time::SCALE < 0); // simple calculations fail due to numeric overflow
CHECK (Time(FSecs(poison)) < Time::ZERO); // conversion to µ-ticks also leads to overflow
CHECK (-6 == _raw(Time(FSecs(poison))));
@ -566,14 +571,68 @@ namespace test {
CHECK (0.671453834f == rational_cast<float> (poison)); // but yields approximately the same effective value
CHECK (0.671453834f == rational_cast<float> (detoxed));
CHECK (detoxed+Time::SCALE == 1172813190450446837_r/1172812402961); // result: we can calculate without failure
CHECK (detoxed+Time::SCALE == 1172813190450446837_r/1172812402961); // result: usual calculations without failure
CHECK (Time(FSecs(detoxed)) > Time::ZERO); // can convert re-quantised number to µ-ticks
CHECK (671453 == _raw(Time(FSecs(detoxed))));
// and resulting µ-ticks will be effectively the same
CHECK (1906 == _raw(TimeValue(1280 / rational_cast<long double>(poison))));
CHECK (1906 == _raw(TimeValue(1280 / rational_cast<long double>(detoxed))));
}
/** @test verify ZoomWindow code can handle "poisonous" Zoom-Factor parameters
*/
void
safeguard_poisonousMetric()
{
ZoomWindow win{};
CHECK (win.visible() == win.overallSpan()); // by default window spans complete canvas
CHECK (win.visible().duration() == _t(23)); // ...and has just some handsome extension
CHECK (win.px_per_sec() == 25);
CHECK (win.pxWidth() == 575);
Rat poison{_raw(Time::MAX)-101010101010101010, _raw(Time::MAX)+23};
CHECK (0 < poison and poison < 1);
win.setMetric (poison); // inject an evil new value for the metric
CHECK (win.visible() == win.overallSpan()); // however, nothing happens
CHECK (win.visible().duration() == _t(23)); // since the window is confined to overall canvas size
CHECK (win.visible() == TimeSpan(_t(0), _t(23))); // Note: this calculation is fail-safe
CHECK (win.px_per_sec() == 25);
CHECK (win.pxWidth() == 575);
win.setOverallDuration(Duration(Time::MAX)); // second test: expand canvas to allow for actual adjustment
CHECK (win.overallSpan().duration() == TimeValue{307445734561825860}); // now canvas has ample size (half the possible maximum size)
CHECK (win.overallSpan().duration() == Time::MAX);
CHECK (win.visible().duration() == _t(23)); // while the visible part remains unaltered
win.setMetric (poison); // Now attempt again to poison the zoom calculations...
CHECK (win.overallSpan().duration() == Time::MAX); // overall canvas unchanged
CHECK (win.visible().duration() == TimeValue{856350691}); // visible window expanded (a zoom-out, as required)
CHECK (win.px_per_sec() == Rat{win.pxWidth()} / _FSecs(win.visible().duration()));
float approxPoison = rational_cast<float> (poison); // the provided (poisonous) metric factor...
CHECK (approxPoison == 0.671453834f); // ...is approximately the same...
float approxNewMetric = rational_cast<float> (win.px_per_sec()); // ...as the actual new metric factor we got
CHECK (approxNewMetric == 0.671453893f);
CHECK (win.px_per_sec() != poison); // but it is not exactly the same
CHECK (win.px_per_sec() < poison); // rather, it is biased towards slightly smaller values
Rat poisonousDuration = win.pxWidth() / poison; // Now, to demonstrate this "poison" was actually dangerous
CHECK (poisonousDuration == 7071251894921995309_r/8257425342068994); // ...when we attempt to calculate the new duration directly....
CHECK (Time(poisonousDuration) < Time::ZERO); // ...then a conversion to TimeValue will cause integer wrap
CHECK(856.350708f == rational_cast<float> (poisonousDuration)); // yet numerically the duration actually established is almost the same
CHECK(856.350708f == rational_cast<float> (_FSecs(win.visible().duration())));
CHECK (win.px_per_sec() == 575000000_r/856350691); // the new metric however is comprised of sanitised fractional numbers
CHECK (win.pxWidth() == 575); // and the existing pixel width was not changed
}
/** @test verify ZoomWindow code can handle extreme zoom-out
* to reveal a timeline of epic dimensions....
*/
void
safeguard_extremeZoomOut()
{
// SHOW_EXPR(win.overallSpan());
// SHOW_EXPR(_raw(win.visible().duration()));
// SHOW_EXPR(win.px_per_sec());
@ -582,6 +641,22 @@ namespace test {
// CHECK (win.px_per_sec() == 25);
// CHECK (win.pxWidth() == 575);
}
/** @test verify ZoomWindow code can navigate extremal time positions.
*/
void
safeguard_extremeTimePos()
{
}
/** @test verify ZoomWindow code is protected against excess scrolling.
*/
void
safeguard_extremeOffset()
{
}
};

View file

@ -39653,14 +39653,23 @@
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1668703282413" HGAP="-88" ID="ID_1113812536" MODIFIED="1668703442612" TEXT="Input (changedMetric) mu&#xdf; entgiftet werden" VSHIFT="23">
<edge COLOR="#f74141" STYLE="linear"/>
<icon BUILTIN="clanbomber"/>
<node COLOR="#338800" CREATED="1669473799874" ID="ID_1081409038" MODIFIED="1669473855697" TEXT="detox">
<edge COLOR="#5e51c9"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668703200176" ID="ID_1915595988" MODIFIED="1668703230862" TEXT="conformMetricToWindow()">
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668703200176" ID="ID_1915595988" MODIFIED="1669479310199" TEXT="conformMetricToWindow()">
<linktarget COLOR="#65253d" DESTINATION="ID_1915595988" ENDARROW="Default" ENDINCLINATION="9;-40;" ID="Arrow_ID_382076752" SOURCE="ID_1175951405" STARTARROW="None" STARTINCLINATION="-11;29;"/>
<linktarget COLOR="#6a6a92" DESTINATION="ID_1915595988" ENDARROW="Default" ENDINCLINATION="37;170;" ID="Arrow_ID_1959668732" SOURCE="ID_4317582" STARTARROW="None" STARTINCLINATION="-243;-9;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1668703282413" ID="ID_1976673029" MODIFIED="1668703442613" TEXT="Output mu&#xdf; entgiftet werden">
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1668703282413" ID="ID_1976673029" MODIFIED="1669473783896" TEXT="Output mu&#xdf; entgiftet werden">
<edge COLOR="#f74141" STYLE="linear"/>
<icon BUILTIN="clanbomber"/>
<node COLOR="#338800" CREATED="1669473816376" HGAP="129" ID="ID_1549431699" MODIFIED="1669473872429" TEXT="detox" VSHIFT="4">
<edge COLOR="#5e51c9"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node CREATED="1668703253721" ID="ID_562775888" MODIFIED="1668703454748" TEXT="output &#x27f6; finaler Metrik-Faktor">
<icon BUILTIN="messagebox_warning"/>
@ -39694,6 +39703,7 @@
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668263629246" ID="ID_1257614207" MODIFIED="1668265511791" TEXT="mutateScale (Rat changedMetric)">
<arrowlink COLOR="#e62f5c" DESTINATION="ID_651838862" ENDARROW="Default" ENDINCLINATION="115;-4;" ID="Arrow_ID_1930230162" STARTARROW="None" STARTINCLINATION="-189;14;"/>
<arrowlink COLOR="#6568c0" DESTINATION="ID_909162669" ENDARROW="Default" ENDINCLINATION="-5;-8;" ID="Arrow_ID_1791222915" STARTARROW="None" STARTINCLINATION="-21;18;"/>
<linktarget COLOR="#aa6877" DESTINATION="ID_1257614207" ENDARROW="Default" ENDINCLINATION="271;-11;" ID="Arrow_ID_292335664" SOURCE="ID_1173749705" STARTARROW="None" STARTINCLINATION="314;29;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668265021139" HGAP="52" ID="ID_1943948610" MODIFIED="1668265531172" TEXT="pr&#xfc;fen: sehr kleine Metrik" VSHIFT="-2">
@ -39706,13 +39716,44 @@
<icon BUILTIN="clanbomber"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668784031268" ID="ID_1513611206" MODIFIED="1668784041478" TEXT="die bestehende Duration k&#xf6;nnte sehr gro&#xdf; sein">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1668784196906" ID="ID_1074723893" MODIFIED="1668784217911" TEXT="mit dem Nenner des changeFactor bereis &#xdc;berlauf m&#xf6;glich"/>
<node CREATED="1668784229969" ID="ID_1956828761" MODIFIED="1668784257285" TEXT="neu errechnete Duration k&#xf6;nnte toxisch sein"/>
<node CREATED="1668784295985" ID="ID_1396219141" MODIFIED="1668784307787" TEXT="Rechnung in mutateDuration() k&#xf6;nnte entgleisen"/>
<node CREATED="1668784318075" ID="ID_901869945" MODIFIED="1668784338191" TEXT="wird alles zwar in conformWindowToMetric(changed) aufgefangen..."/>
<node CREATED="1668784339323" ID="ID_1591426559" MODIFIED="1668784345302" TEXT="..is aber trotzdem falsch"/>
</node>
<node COLOR="#435e98" CREATED="1668263638141" ID="ID_909162669" MODIFIED="1668270369633" TEXT="mutateDuration (FSecs duration, uint px =0)">
</node>
<node COLOR="#435e98" CREATED="1668263638141" ID="ID_909162669" MODIFIED="1669477898780" TEXT="mutateDuration (FSecs duration, uint px =0)">
<arrowlink COLOR="#965e8b" DESTINATION="ID_1175951405" ENDARROW="Default" ENDINCLINATION="253;-8;" ID="Arrow_ID_354964355" STARTARROW="None" STARTINCLINATION="302;-12;"/>
<linktarget COLOR="#6568c0" DESTINATION="ID_909162669" ENDARROW="Default" ENDINCLINATION="-5;-8;" ID="Arrow_ID_1791222915" SOURCE="ID_1257614207" STARTARROW="None" STARTINCLINATION="-21;18;"/>
<node CREATED="1668270374842" HGAP="21" ID="ID_1976979366" MODIFIED="1668270395644" TEXT="delegiert an conformWindowToMetric(Rat)" VSHIFT="9">
<icon BUILTIN="idea"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1669479155534" ID="ID_620129730" MODIFIED="1669479162094" TEXT="adaptWindowToPixels(px)">
<node COLOR="#435e98" CREATED="1669479175476" ID="ID_590715378" MODIFIED="1669479353924" TEXT="Arithmetik erscheint ungef&#xe4;hrlich">
<icon BUILTIN="info"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1669479204552" ID="ID_29297928" MODIFIED="1669479365083" TEXT="unter der Annahme da&#xdf; bestehende Metrik sauber ist">
<icon BUILTIN="messagebox_warning"/>
</node>
<node COLOR="#435e98" CREATED="1669479223678" ID="ID_4317582" MODIFIED="1669479361432" TEXT="au&#xdf;erdem: Ausgang durch conformMetricToWindow">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...und das betrachte ich als gutm&#252;tig und hinreichend abgesichert...
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#6a6a92" DESTINATION="ID_1915595988" ENDARROW="Default" ENDINCLINATION="37;170;" ID="Arrow_ID_1959668732" STARTARROW="None" STARTINCLINATION="-243;-9;"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668263652677" ID="ID_759637608" MODIFIED="1668265848826" TEXT="anchorWindowAtPosition (FSecs canvasOffset)">
<linktarget COLOR="#895f96" DESTINATION="ID_759637608" ENDARROW="Default" ENDINCLINATION="124;-7;" ID="Arrow_ID_728050450" SOURCE="ID_1494604965" STARTARROW="None" STARTINCLINATION="168;14;"/>
<icon BUILTIN="flag-yellow"/>
@ -39819,11 +39860,36 @@
</node>
</node>
</node>
<node CREATED="1668554900067" ID="ID_1302892550" MODIFIED="1668554974542" TEXT="kritische Wirkpfade">
<node CREATED="1668555028046" ID="ID_660534369" MODIFIED="1668555056498" TEXT="sehr kleine Metrix (&#x2259; exterm zoom-out)"/>
<node CREATED="1668555072594" ID="ID_742229180" MODIFIED="1668555089126" TEXT="Ansteuern exterm gro&#xdf;er Zeit-Positionen"/>
<node CREATED="1668555157385" ID="ID_1157546672" MODIFIED="1668555164702" TEXT="Time-wrap nach extremem Offset"/>
<node CREATED="1668555183502" ID="ID_1287974241" MODIFIED="1668555191961" TEXT="Einspeisen giftiger Metrik"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1668554900067" HGAP="80" ID="ID_1302892550" MODIFIED="1669473989333" TEXT="kritische Wirkpfade abtesten" VSHIFT="9">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668555028046" ID="ID_660534369" MODIFIED="1669473993482" TEXT="sehr kleine Metrix (&#x2259; exterm zoom-out)">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1669475559599" ID="ID_460741178" MODIFIED="1669475567282" TEXT="setVisiblePos mit giftigem Faktor"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668555072594" ID="ID_742229180" MODIFIED="1669473993488" TEXT="Ansteuern exterm gro&#xdf;er Zeit-Positionen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1669475536331" ID="ID_486161883" MODIFIED="1669475548565" TEXT="setVisiblePos mit extremer Time"/>
<node CREATED="1669475549345" ID="ID_234786683" MODIFIED="1669475556499" TEXT="setVisiblePos mit extremem Faktor"/>
<node CREATED="1669479474484" ID="ID_1657847338" MODIFIED="1669479489366" TEXT="alle Mutatoren, die conformWindowToMetric() verwenden"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668555157385" ID="ID_1157546672" MODIFIED="1669473993486" TEXT="Time-wrap nach extremem Offset">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1668555183502" ID="ID_1287974241" MODIFIED="1669488176332" TEXT="Einspeisen giftiger Metrik">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1669478124298" ID="ID_1987069808" MODIFIED="1669488168358" TEXT="Fall-1 : kappen auf Canvas-Grenzen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1669478154709" ID="ID_499422673" MODIFIED="1669488173372" TEXT="Fall-2 : hinreichend gro&#xdf;er Canvas">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1669479930775" ID="ID_196873456" MODIFIED="1669480034941" TEXT="Fall-3 : setVisiblePos mit giftigem faktor">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1669480019215" ID="ID_930072077" MODIFIED="1669480034942" TEXT="Fall-4 : setVisiblePos mit extrem entfernter Position">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1668180030777" ID="ID_1319796356" MODIFIED="1668180136077" TEXT="1 &#xb5;-Tick">