mirror of
https://github.com/Shadowss/TravianZ.git
synced 2026-07-11 07:06:06 +00:00
fix(market): harden NPC resource distribution against NaN [#211]
On some servers the NPC ("merchant") distribution screen could lock on
"Rest: NaN", hiding the trade button and making the NPC unusable. The "Rest"
value never returned to 0, so the player could not complete the trade.
Two layers of hardening:
* Client (Templates/Build/17_3.tpl):
- add a safe npcDiv() helper (returns 0 on a 0 divisor or non-finite value)
and route every division in portionOut() through it, so Infinity/NaN can no
longer leak into the inputs;
- in calculateRest(), coerce "Rest"/overall to a finite value (fall back to
the total when org4 cannot be parsed) so the submit button can always
reappear once the distribution is balanced;
- coerce each resource, $totalRes, $maxstore and $maxcrop to a valid,
non-negative integer before they reach the page/JS, so a resource computed
as NaN/INF cannot poison org4/summe in the first place.
* Server (Market::tradeResource): clamp each requested amount to [0, maxstore]
(crop to maxcrop) before persisting, so a forged or corrupted POST can no
longer write out-of-range resources.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+16
-31
@@ -806,35 +806,20 @@ class Market
|
||||
exit;
|
||||
}
|
||||
|
||||
// Prevent selling more resources than available
|
||||
if (
|
||||
(
|
||||
(int)$post['m2'][0] < 0 &&
|
||||
round($village->awood) + (int)$post['m2'][0] < 0
|
||||
) ||
|
||||
(
|
||||
(int)$post['m2'][1] < 0 &&
|
||||
round($village->aclay) + (int)$post['m2'][1] < 0
|
||||
) ||
|
||||
(
|
||||
(int)$post['m2'][2] < 0 &&
|
||||
round($village->airon) + (int)$post['m2'][2] < 0
|
||||
) ||
|
||||
(
|
||||
(int)$post['m2'][3] < 0 &&
|
||||
round($village->acrop) + (int)$post['m2'][3] < 0
|
||||
)
|
||||
) {
|
||||
// Sanitize the requested distribution: never negative, never above the
|
||||
// warehouse / granary capacity. Guards against a forged or NaN-corrupted
|
||||
// POST (issue #211: NPC distribution).
|
||||
$maxstore = (int) $village->maxstore;
|
||||
$maxcrop = (int) $village->maxcrop;
|
||||
|
||||
header('Location: build.php?id=' . $post['id'] . '&t=3');
|
||||
exit;
|
||||
}
|
||||
$m2 = [
|
||||
max(0, min($maxstore, (int)($post['m2'][0] ?? 0))),
|
||||
max(0, min($maxstore, (int)($post['m2'][1] ?? 0))),
|
||||
max(0, min($maxstore, (int)($post['m2'][2] ?? 0))),
|
||||
max(0, min($maxcrop, (int)($post['m2'][3] ?? 0))),
|
||||
];
|
||||
|
||||
$newTotal =
|
||||
(int)$post['m2'][0] +
|
||||
(int)$post['m2'][1] +
|
||||
(int)$post['m2'][2] +
|
||||
(int)$post['m2'][3];
|
||||
$newTotal = $m2[0] + $m2[1] + $m2[2] + $m2[3];
|
||||
|
||||
$currentTotal =
|
||||
round($village->awood) +
|
||||
@@ -853,10 +838,10 @@ class Market
|
||||
$village->wid,
|
||||
['wood', 'clay', 'iron', 'crop'],
|
||||
[
|
||||
$post['m2'][0],
|
||||
$post['m2'][1],
|
||||
$post['m2'][2],
|
||||
$post['m2'][3]
|
||||
$m2[0],
|
||||
$m2[1],
|
||||
$m2[2],
|
||||
$m2[3]
|
||||
]
|
||||
);
|
||||
$this->forget();
|
||||
|
||||
Reference in New Issue
Block a user