← Back to context

Comment by axblount

2 days ago

This is usually called NaN-boxing and is often used to implement dynamic languages.

https://piotrduperas.com/posts/nan-boxing

I wonder if IEEE-754 designers anticipated this use case during development. Great article - this kind of "outside-the-normal-use-case" requires a very careful reading of the specifications/guarantees of the language.

  • IEEE-754 seems to say that NaN payloads are designed to contain "retrospective diagnostic information inherited from invalid or unavailable data and results". While NaN boxing in particular probably wasn't the intention, untouched payloads in general absolutely were.

Are there any security implications of NaN-Boxing?

If I encode data into the exponent of these NaN values, propagate them around the internet, and decode them elsewhere.... is that a security risk? Or this just falls into the category of "weird encryption"

  • Define security risk. Obviously this data could come from untrusted sources. Another consideration is that this data may not serialize correctly: most text serialization protocols will not distinguish different NaN values. It's possible for there to be some data confusion in your pipeline as well, if you don't control all the code that touches those bytes.

  • I'd be surprised. It's surprisingly difficult to setialize NaN values. Can't do it on JSON, for example.

Like JavaScript. Which should immediately raise the question how it could possibly work on engines that employ it themselves. Turns out... it won't.

I appreciate this article a lot more because it contains an iota of benchmarking with an explanation about why this might be more performant. Especially since my first thought was 'wouldn't this require more instructions to be executed?'

The original post seems really weird to me. I would have dismissed it as someone's hobby project, but... that doesn't seem like what it's trying to be.

  • "More instructions to execute" is not synonymous with "slower".

    NaNboxing lets you use less memory on certain use cases. Because memory access is slow and caches are fixed size, this is usually a performance win, even if you have to do a few extra ops on every access.

    • I mean, a modern computer is operating the gigahertz range. Adding a few extra bitwise instructions might be something like a nanosecond. Which is absolutely fleeting compared to memory operations.