mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
fix(savedata): guard against sub-minimum backup data in recovery
nullcomp's passthrough path returns non-cmp-header data as-is without error, which is correct for old uncompressed saves. However, a corrupt backup slot containing garbage shorter than the minimum save layout (100 bytes) would pass Decompress() and then panic in updateStructWithSaveData() with a slice-bounds error at the name field read (offset 88–100). Add a minSaveSize check after each backup decompresses; skip the slot if the result is too small. Also document the campaign system and the fix in CHANGELOG under Unreleased.
This commit is contained in:
@@ -7,8 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed backup recovery panic: `recoverFromBackups` now rejects decompressed backup data smaller than the minimum save layout size, preventing a slice-bounds panic when nullcomp passes through garbage bytes as "already decompressed" data ([#182](https://github.com/Mezeporta/Erupe/pull/182)).
|
||||
|
||||
### Added
|
||||
|
||||
- Event Tent (campaign) system: code redemption, stamp tracking, reward claiming, and quest gating for special event quests, backed by 8 new database tables and seeded with community-researched live-game campaign data ([#182](https://github.com/Mezeporta/Erupe/pull/182), by stratick).
|
||||
- Database migration `0010_campaign` (campaigns, campaign_categories, campaign_category_links, campaign_rewards, campaign_rewards_claimed, campaign_state, campaign_codes, campaign_quest).
|
||||
- JSON Hunting Road config: `bin/rengoku_data.json` is now supported as a human-readable alternative to the opaque `rengoku_data.bin` — the server assembles and ECD-encrypts the binary at startup, with `.bin` used as a fallback ([#173](https://github.com/Mezeporta/Erupe/issues/173)).
|
||||
- JSON quest files: `.json` files in `bin/quests/` are now supported alongside `.bin` — the server tries `.bin` first (full backward compatibility), then compiles `.json` on the fly to the MHF binary wire format ([#160](https://github.com/Mezeporta/Erupe/issues/160)). Covers all binary sections: quest text (UTF-8 → Shift-JIS), all 12 objective types, monster spawns (large + minion), reward tables, supply box, loaded stages, rank requirements, variant flags, forced equipment, map sections, area transitions, coordinate mappings, map info, gathering points, gathering tables, and area facilities. A `ParseQuestBinary` reverse function allows existing `.bin` files to be inspected and exported to JSON.
|
||||
|
||||
|
||||
@@ -114,6 +114,19 @@ func recoverFromBackups(s *Session, base *CharacterSaveData, charID uint32) (*Ch
|
||||
continue
|
||||
}
|
||||
|
||||
// nullcomp passes through data without a "cmp" header as-is (legitimate for
|
||||
// old uncompressed saves). Guard against garbage data that is too small to
|
||||
// contain the minimum save layout (name field at offset 88–100).
|
||||
const minSaveSize = saveFieldNameOffset + saveFieldNameLen
|
||||
if len(candidate.decompSave) < minSaveSize {
|
||||
s.logger.Warn("Backup slot data too small after decompression, skipping",
|
||||
zap.Uint32("charID", charID),
|
||||
zap.Int("slot", backup.Slot),
|
||||
zap.Int("size", len(candidate.decompSave)),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
s.logger.Warn("Savedata recovered from backup — primary was corrupt",
|
||||
zap.Uint32("charID", charID),
|
||||
zap.Int("slot", backup.Slot),
|
||||
|
||||
Reference in New Issue
Block a user