aboutsummaryrefslogtreecommitdiff
path: root/internal/player
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-18 15:16:44 -0400
committerhistoria <[not public]>2026-09-18 15:16:44 -0400
commit7eab582d8a8ee2af1a6baae7baf0696c7005de2e (patch)
tree902bbc8c6e39c9f62f779ca23267714ec420b9f5 /internal/player
parent153acb7f644d755c45533b7c5311e3ffa47e8973 (diff)
downloadthehouseoficarus-7eab582d8a8ee2af1a6baae7baf0696c7005de2e.tar.gz
fix: harden triggers, economy, casino, world data, and admin/net paths
Diffstat (limited to 'internal/player')
-rw-r--r--internal/player/hardening_removeitem_test.go23
-rw-r--r--internal/player/player.go6
2 files changed, 29 insertions, 0 deletions
diff --git a/internal/player/hardening_removeitem_test.go b/internal/player/hardening_removeitem_test.go
new file mode 100644
index 0000000..5cb1e4c
--- /dev/null
+++ b/internal/player/hardening_removeitem_test.go
@@ -0,0 +1,23 @@
+package player
+
+import "testing"
+
+// TestRemoveItemRejectsNonPositive: a non-positive quantity must never mutate
+// a stack; a negative value used to increase it.
+func TestRemoveItemRejectsNonPositive(t *testing.T) {
+ p := New("alice")
+ p.SetInvSlot(0, &InventorySlot{ItemID: "coin", Quantity: 5})
+
+ if p.RemoveItem("coin", -3) {
+ t.Fatal("negative quantity accepted")
+ }
+ if slot := p.InvSlot(0); slot == nil || slot.Quantity != 5 {
+ t.Fatalf("stack mutated by a negative removal: %+v", slot)
+ }
+ if p.RemoveItem("coin", 0) {
+ t.Fatal("zero quantity accepted")
+ }
+ if slot := p.InvSlot(0); slot == nil || slot.Quantity != 5 {
+ t.Fatalf("stack mutated by a zero removal: %+v", slot)
+ }
+}
diff --git a/internal/player/player.go b/internal/player/player.go
index f8d9a68..efa906b 100644
--- a/internal/player/player.go
+++ b/internal/player/player.go
@@ -510,6 +510,12 @@ func (p *Player) CountItem(itemID string) int {
}
func (p *Player) RemoveItem(itemID string, qty int) bool {
+ // A non-positive quantity must never mutate a stack: with qty < 0 the
+ // subtraction below would increase it. Callers pass positive quantities;
+ // reject anything else instead of creating items from a data typo.
+ if qty <= 0 {
+ return false
+ }
remaining := qty
for i, slot := range p.Inventory {
if slot == nil || slot.ItemID != itemID {