Article 4XTX3 CodeSOD: An Unreal Json Parser

CodeSOD: An Unreal Json Parser

by
Remy Porter
from The Daily WTF on (#4XTX3)

As we've discussed in the past, video game code probably shouldn't be held to the standards of your average WTF: they're operating under wildly different constraints. So, for example, when a popular indie game open sources itself, and people find all sorts of horrors in the codebase: hey, the game shipped and made money. This isn't life or death stuff.

It's a little different when you're building the engine. You're not just hacking together whatever you need to make your product work, but putting together a reusable platform to make other people's products work.

Rich D, who previously shared some horrors he found in the Unreal engine, recently discovered that UnrealScript has a useful sounding JsonObject. Since Rich is thinking in terms of mods, being able to read/write JSON to handle mod configuration is useful, but anyone designing a game might have many good reasons to want JSON documents.

The file starts promisingly with:

class JsonObject extends Objectnative;/// COMMENT!!"

It's good that someone put that comment there, because I assume it was meant as a reminder: comment this code. And the comments start giving us hints of some weird things:

/** * Looks up a value with the given key in the ObjectMap. If it was a number * in the Json string, this will be prepended with \# (see below helpers) * * @param Key The key to search for * * @return A string value */native function string GetStringValue(const string Key);

The method GetStringValue returns a string from JSON, but if the string is a number, it" puts a \# in front of it? Why?

function int GetIntValue(const string Key){local string Value;// look up the key, and skip the \#Value = Mid(GetStringValue(Key), 2);return int(Value);}

Oh" that's why. So that we can ignore it. There's a similar version of this method for GetFloatValue, and GetBoolValue.

So, how do those \#s get prepended? Well, as it turns out, there are also set methods:

function SetIntValue(const string Key, int Value){SetStringValue(Key, "\\#" $ Value);}

In addition to these methods, there are also native methods (e.g., methods which bind to native code, and thus don't have an UnrealScript body) to encode/decode JSON:

/** * Encodes an object hierarchy to a string suitable for sending over the web * * @param Root The toplevel object in the hierarchy * * @return A well-formatted Json string */static native function string EncodeJson(JsonObject Root);/** * Decodes a Json string into an object hierarchy (all needed objects will be created) * * @param Str A Json string (probably received from the web) * * @return The root object of the resulting hierarchy */static native function JsonObject DecodeJson(const string Str);

Guided by this code, Rich went on to do a few tests:

  • Calling SetStringValue with a string that happens to start with \# causes EncodeJson to produce malformed output.
  • Calling SetStringValue with any string that might require escape characters (newlines, backslashes, etc.) will not escape those characters, producing malformed output.
  • Which means that the output of EncodeJson cannot reliably be parsed by DecodeJson, as sometimes the output is invalid
  • Sometimes, when DecodeJson receives an invalid document, instead of throwing an error, it just crashes the entire game

Rich has wisely decided not to leverage this object, for now.

proget-icon.png [Advertisement] Ensure your software is built only once and then deployed consistently across environments, by packaging your applications and components. Learn how today! TheDailyWtf?d=yIl2AUoC8zAkRqjMquMwKg
External Content
Source RSS or Atom Feed
Feed Location http://syndication.thedailywtf.com/TheDailyWtf
Feed Title The Daily WTF
Feed Link http://thedailywtf.com/
Reply 0 comments