[FIX] computeFair: validazione range input (no overflow DECIMAL, no negativi/NaN/vuln>1) - finding review

TEF cap 1M ev/anno, LM cap 1000 mld EUR -> ALE resta entro DECIMAL(16,2). Rifiuta valori
negativi/non finiti e vuln>1 con 422. Verificato E2E: valido 200; LM enorme/vuln>1/negativo -> 422.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile 2026-05-30 12:15:13 +02:00
parent a3f821122a
commit d89f73bf2d

View File

@ -340,6 +340,12 @@ class RiskController extends BaseController
$this->jsonError('Rischio non trovato', 404, 'NOT_FOUND');
}
// Limiti coerenti con le colonne DB per evitare overflow:
// fair_tef_* DECIMAL(10,2) -> max ~99.999.999 | fair_lm_* DECIMAL(14,2) -> max ~999 mld
// ale_* DECIMAL(16,2). Cappiamo TEF e Loss Magnitude a valori realistici così che
// ALE = TEF * vuln * LM resti entro DECIMAL(16,2).
$TEF_MAX = 1000000.0; // 1M eventi/anno (limite prudenziale)
$LM_MAX = 1000000000000.0; // 1.000 mld EUR per evento
$params = [
'tef_min' => (float) $this->getParam('tef_min', 0),
'tef_ml' => (float) $this->getParam('tef_ml', 0),
@ -349,6 +355,25 @@ class RiskController extends BaseController
'lm_ml' => (float) $this->getParam('lm_ml', 0),
'lm_max' => (float) $this->getParam('lm_max', 0),
];
// Validazione: niente valori negativi o NaN/inf
foreach ($params as $k => $v) {
if (!is_finite($v) || $v < 0) {
$this->jsonError("Parametro FAIR non valido: {$k}", 422, 'INVALID_FAIR_PARAM');
}
}
foreach (['tef_min', 'tef_ml', 'tef_max'] as $k) {
if ($params[$k] > $TEF_MAX) {
$this->jsonError("Frequenza eventi ({$k}) oltre il limite ammesso ({$TEF_MAX})", 422, 'FAIR_OUT_OF_RANGE');
}
}
foreach (['lm_min', 'lm_ml', 'lm_max'] as $k) {
if ($params[$k] > $LM_MAX) {
$this->jsonError("Magnitudo di perdita ({$k}) oltre il limite ammesso ({$LM_MAX})", 422, 'FAIR_OUT_OF_RANGE');
}
}
if ($params['vuln'] > 1) {
$this->jsonError('La vulnerabilità deve essere compresa tra 0 e 1', 422, 'FAIR_OUT_OF_RANGE');
}
$iterations = (int) $this->getParam('iterations', FairService::DEFAULT_ITERATIONS);
$sim = FairService::simulate($params, $iterations);