Fix/persisted player map flag - #126
Conversation
| // Many commands and features that require a duration can be satisfied by specifying a number and unit of time, especially command arguments that are prefixed 'duration:', etc. | ||
| // The unit of time can be specified by using one of the following: | ||
| // t=ticks (0.05 seconds), s=seconds, m=minutes (60 seconds), h=hours (60 minutes), d=days (24 hours), w=weeks (7 days), y=years (365 days). | ||
| // ms=milliseconds (0.001 seconds), t=ticks (0.05 seconds), s=seconds, m=minutes (60 seconds), h=hours (60 minutes), d=days (24 hours), w=weeks (7 days), y=years (365 days). |
- avoid dereferencing quickMap when a persisted `map`@ value fails MapTag parsing - treat value as a literal instead, rewrite it in the unambiguous el@ form on save to preserve the raw value and allows unrelated player flags to load normally
b24c0a6 to
f36cd61
Compare
|
Can you clarify how exactly an invalid map is getting stored there? There should be protections in the code to prevent that from happening in the first place. |
|
i'll need some help with words, but basically what's happening is the player flag is wrapped as a root uses PropertyParser.escapePropertyValue(...)then, around here, it sees the first [, the last ], and decides that the whole region is valid object property syntax so it preserves that instead of escaping it. this is fine for real nested object properties but these bad chat_history_list values contain magic Denizen formatting here. that text was sneaking through the property syntax and when read back, MapTag.valueOf treats that [ and ] as map nesting and a raw ; to then look like a new map entry, which, when it reaches plain text such as - where it expects key=value, it returns null, the old cleanup then code dereferences that.So I think the NPE fix is still correct as protection for existing bad data, but the serializer escaping behavior is likely the reason this data could be written in the first place. to answer your question in regards to a script, it's actually very hard to do. something like this: map_escape_repro:
type: world
events:
on player joins:
- define chat_text "<&ss>[click=RUN_COMMAND;/help]hello; world<&ss>[/click]"
- flag <player> chat_history_list:<list[<[chat_text]>]> expire:1hyou would:
in this example, it effectively generates the plaintext |
|
So the flag contains a real flag-data-map, but the readback is corrupted by invalid escaping? This sounds like an X/Y problem where this PR is addressing the Y but we need to fix the X (the bad escaping logic) |
|
that exactly, yes basically. the readback is not corrupting a valid map because the map is already written in an invalid form. our magic denizen the X is the serializer escaping/round-trip issue that allowed it to be written - but i felt like i would have been told it should be fixed separately or added here if you prefer the broader scope because that feels much bigger than just this issue, it branches off into separate things that extend past what i touched here; should i go for that next? |
|
to clarify also i do not mind taking on the next step of this if it extends to another pull request - but from what i found is that |
Summary
fixes a
SavableMapFlagTracker.doTotalClean()NPE caused by persisted flag values that begin withmap@but cannot be parsed as valid MapTagsProblem
the cleanup optimization parsed these values into
quickMapand immediately dereferenced the result; for malformed map-like values, parsing returns null.Changes
map@...value as a literal flag value;el@map@...;this was reproduced with real archived player-flag data; a malformed
chat_history_listrecord could cause an unrelated<server.players_flagged[fishing_list]>lookup to fail, because loading a player tracker cleans all of that player’s flagsTesting:
it takes several steps to replicate, so here's each step:
https://paste.denizenscript.com/View/141477 - shows me throwing the async cleanup NPE
https://paste.denizenscript.com/View/141478 - shows the exact outer
<server.players_flagged[fishing_list]>throwingquickMapis nullhttps://paste.denizenscript.com/View/141479 - fixed: same real profile/data and outer tag; it returns 1.