10 ms·
Json ⊄ js
- Rauchg 14y agoMagnus Holm did a great job describing this after he fixed the problem in Rack::JSONP. Good reference as well for those interested in the topic: http://timelessrepo.com/json-isnt-a-javascript-subset http://timelessrepo.com/json-isnt-a-javascript-subset
- 0x0 14y agoWhat a shame that \u hack isn't acceptable in javascript, http://code.google.com/p/v8/issues/detail?id=1939#c4 http://code.google.com/p/v8/issues/detail?id=1939#c4
- coolj 14y ago> The abstract operation Quote(value) wraps a String value in double quotes and escapes characters within it. It doesn't look like http://es5.github.com/#Quote http://es5.github.com/#Quote has anything to do with serializing to JSON string--am I missing something?
- lucian1900 14y agoPetty much all web technologies appear to be made of twine and duck tape. It's so sad that this is in many cases the best we have.
- tubbo 14y agoComputers are looking more and more like reality every day.
- deleted 14y ago[deleted]
- Already__Taken 14y agoThat just seems to be what happens when so many people have to collaborate. Plus its still just mega young. Look at legal systems, they've been around forever and it can be your life's work just to understand them at a competency to participate. The miracle of software isn't that it works, it's that it does anything at all.
- rwmj 14y agoThat's ridiculous. JSON is replacing XML which is a well-established interchange technology that doesn't have all the problems of JSON (like no good way to represent 64 bit numbers, weak typing, barely any types in the first place, etc).
- masklinn 14y ago> like no good way to represent 64 bit numbers Yep, it only has strings either way. > weak typing Yep, it only has strings either way (also, "weak typing" does not mean jack shit, and talking about typing strength for a serialization format makes zero sense) > barely any types in the first place Yep, it only has one.
- aurelianito 14y agoIf you look at the XML schema specs (http://www.w3.org/TR/2000/CR-xmlschema-2-20001024/#decimal http://www.w3.org/TR/2000/CR-xmlschema-2-20001024/#decimal) you will see that they have been standardized numbers. Things in XML do not need to be just strings. PS: I still don't like XML, but your comment is technically incorrect. Edit: Typo FIX.
- masklinn 14y ago> Things in XML do not need to be just strings. Things in XML are just strings. Schemas are metadata, annotations to tell processors "treat this string as [some other datatype]" (note how it's not going to work if you're not using the schema and a schema-aware processor?) And guess what? Nothing stops you from doing exactly the same thing in JSON. In fact you don't have much of a choice for the datatypes JSON doesn't natively support (dates being the most common one, but not the only one by any mean). And good JSON interfaces provide for embedding transcodings directly in the parsing or dumping (that's what the `reviver` and `replacer` arguments do in JSON.parse and JSON.stringify) for exactly that purpose. > PS: I still don't like XML, but your comment is technically incorrect. Nope. Specific XML dialects may have non-string datatypes (XML-RPC certainly does), but XML only has strings. In the same way CSV only has strings, but specific CSV uses may have more. That's the plain facts of the matter.
- protonfish 14y agoThat's quite a conclusion to jump to. Maybe you haven't noticed but the Web is running great, especially when developed by thoughtful, competent programmers. It's sad how many non-web developers still complain about how the Web is sour grapes.
- dllthomas 14y agoIt's not that the people working on it haven't been great, it's that there's so much path dependence, it's frustrating. Which is not at all to say that there isn't path dependence in plenty of other domains.
- beatgammit 14y agoOne more thing that really bugs me about JSON is that it doesn't support Infinity, -Infinity and NaN. Python's JSON library does, which leads to some interesting breakages. Sure, for NaN you can use null, but for Infinity, you have to use really large/small numbers, which can also lead to other problems.
- udp 14y agoIf Python's JSON library accepts Infinity by default, that's a bug and should be reported.
- enaeseth 14y agoYou can try to report it as a bug, but the docs indicate that this is by design.
- JulianWasTaken 14y agoIt isn't. It's documented behavior. See http://docs.python.org/2/library/json.html http://docs.python.org/2/library/json.html. (simple)JSON deviates from the spec in a few minor ways.
- andrewcooke 14y agomore exactly, it's an option you can disable.
- Mooby 14y agoThat isn't JSON's problem. It's your app's problem. Set your parser to recognize "Infinity" as a token and you are set.
- fdr 14y agoPerhaps more pervasive and despairingly problematic is number representation. JSON only, per specification, supports arbitrary precision numeric representation. However, Javascript is -- also per specification (as I understand it) -- entirely floating point. That makes working with money in Javascript somewhat hazardous. While there are various arbitrary precision libraries out there for Javascript to assuage this, the problem is most JSON-parsing routines will always force one through a floating point conversion anyway, so a loss of precision is more or less inevitable. While swiftly coercing raw off-the-wire number representations to one's arbitrary precision library of choice can avoid most cases of noticeable accumulated error, it is irksome that the only way everyone seems to get by is by cross their fingers that any loss in precision caused by "JSON.parse" is meaningless to their application. Or, the problem can be soundly avoided by using strings in the JSON payload, which is lame but effective and probably one's best practical choice. It is clearly an example of corruption spreading from Javascript to an otherwise reasonable feature of the data representation format JSON.
- mikeash 14y agoJavaScript uses IEEE754 doubles for numbers, so as long as you can count on all of your parsers to do that, then you can rely on any integer up to 2^54 being represented exactly. For money, work in cents.
- chris_mahan 14y agoYou mean, for American money, work in cents.
- rys 14y agoThe name cent shouldn't throw you off here as applying only to US currency. Many other currencies have a notional 1/100th unit of the basic one, that usually also exists as a cash value.
- xnxn 14y agoSo s/cent/atomic subunit/, because "for money, work in cents" is meaningless for yen and ambiguous for Bitcoin ("bitcents" or "satoshis"?)
- andrewcooke 14y agoanyone else see the strangest mess on view source for that page? (chrome on ubuntu) [edit: i guess it's confused by the line break characters. i reported an issue.] [edit2: whoa, wget seems to show the same thing when i look at the source in emacs...] [edit3: ok, i am an idiot. it's just quotes in a bunch of meta tags. sorry. move along. nothing to see here.]
- prezjordan 14y agoI'm curious why every paragraph is named like that.
- xmas_project 14y agoThe "uniname" command in the uniutils package (apt-get install uniutils) is great for checking "invisible" or weird Unicode characters. `echo '{"str": "own ed"}' | uniname` will show the LINE SEPARATOR (\u002028) hidden in the string.
- lacker 14y agoAnother problem is unicode characters that are not in the basic multilingual plane. JSON supports those, but many Javascript environments (like basically all browsers) do not.
- Mooby 14y agolooks like the real problem lies in some libraries being broken and poorly thought out. If your code chokes on invalid input then the problem lies in your code, not the input.
- JulianMorrison 14y agoThe other reason: if you are using a Turing-complete language to eval your nominally context free grammar as if it were code, you are an idiot who is asking to be hacked, whether through quirks like this or otherwise. (This also goes for PHP and ERB.) http://www.cs.dartmouth.edu/~sergey/langsec/occupy/ http://www.cs.dartmouth.edu/~sergey/langsec/occupy/
- Rauchg 14y agoIt's actually trivial to make evaluation safe for JSON input as seen in the very short `parseJSON` implementation in jQuery: https://github.com/jquery/jquery/blob/master/src/core.js#L523 https://github.com/jquery/jquery/blob/master/src/core.js#L52... Also, for the JSONP technique to work, it _has_ to be valid JavaScript so the escaping is necessary.
- chimeracoder 14y agoI don't know enough Javascript to give the analogous exploit myself, but that approach looks dangerously similar to some attempts I have seen at making Python's "eval" safe - attempts which, I might add, all fail to capture corner cases that any sufficiently determined or motivated attacker would eventually discover.
- fforw 14y agoFirst of all, if native JSON parsing exists, jQuery will use that. The validation code they use in case there is no native JSON implementation available is borrowed from Douglas Crockford's json2.js ( https://github.com/douglascrockford/JSON-js/blob/master/json2.js#L448 https://github.com/douglascrockford/JSON-js/blob/master/json... ) which was the inspiration for the native JSON implementations and should really be correct by now, both in terms of correctness but also circumventing regexp weaknesses in some engines.
- JulianMorrison 14y agoIt's still the Wrong Way™. You want to parse JSON, you write a lexer that recognizes its symbols and a parser that consumes them and spits the JS equivalent. Otherwise you are playing an eternal game of whack-a-mole with the JS eval parser. No. Just no.
- ot 14y agoPrevious discussion: http://news.ycombinator.com/item?id=2550145 http://news.ycombinator.com/item?id=2550145
- sil3ntmac 14y agoI often pass inline data from server -> client JS using a meta tag. In rails3 it would look like: <meta name='blah' content="<%= @data.to_json %>" /> However this has always seemed unclean to me. Does anyone else have a better, alternative method of inlining data? I'd rather not use inline scripts for the exact reason they mention.
- scalvert 14y agoWe use this technique https://www.quora.com/JavaScript/What-is-the-best-way-to-pass-server-side-variables-to-client-side-JavaScript https://www.quora.com/JavaScript/What-is-the-best-way-to-pas...
- jasonkostempski 14y agoCan you give it directly to the JS working on that data by setting a var (var x = <%= @data.to_json %>;) or passing it in as a parameter to an initializing function call (APP.init(<%= @data.to_json %>);)? Edit: 1. I hope it's not user generated data. 2. The output in this case wouldn't need to be JSON syntax, it could be object literal notation, saving space on all those double quotes but I doubt you have a helper method available for that.
- ricardobeat 14y agoUse data-* attributes [1], or print it in a script tag with a text/anything type: <script type="text/json" id="mydata"> { data: "..." } </script> var data = JSON.parse($('mydata').textContent) [1] https://developer.mozilla.org/en-US/docs/HTML/Global_attributes#attr-data-* https://developer.mozilla.org/en-US/docs/HTML/Global_attribu...
- benmmurphy 14y agoIf you put it in a script tag you need to ensure you escape </script>. Though, it is probably safer to escape <, >, and & just to be sure.
- fforw 14y ago
- javajosh 14y agoThis is a good catch, but the presentation is awfully passive aggressive. Yes, if JSON wants to strictly be a subset of JS, then those two characters need to be treated specially - either excluded from JSON, or specially escaped in JSON libraries. The simplest solution, clearly, is to exclude them from JSON. (You can still use those characters, but you have to escape them). There's no compelling reason not to do this - and I doubt that this will cause a problem anyway.
- gurkendoktor 14y agoIf you can paste these invisible characters into a chat box to break a website that uses eval(), then someone will inevitably do it, simply because it is the internet.
- powrtoch 14y agoI feel really dense, but I don't understand why the example line is throwing an error. The article mentions line terminators, but it doesn't seem to contain any, and I also don't understand why "owned" would be escaped the way the author says... it looks as though the interpreter is just rejecting the use of quotes around the key. But I'm sure I'm just missing something, so I'd be much obliged if someone could enlighten me.
- tjohns 14y agoThe line terminator is there, it just doesn't render as anything visible. (It's inserted directly as a unicode character, rather than it's HTML-escaped equivalent, so you won't even see it if you view source!) However, if you take a hex dump of the page, it becomes quite apparent: https://gist.github.com/4393892 https://gist.github.com/4393892 Note: The file is UTF-8 encoded, so you'd be looking for E2 80 A8 instead of \u2028.
- jfarmer 14y agoThere's an invisible-to-the eye unicode character in the string "owned," if you copy and paste the text from the website. JSON is fine with these characters, but JavaScript is not. For plain-jane JSON this is usually fine, since you're not just evaluating the JSON as JavaScript, but are running the returned data through a JSON parser. A properly-designed JSON parser will escape any JSON-valid-but-JavaScript-invalid characters. JSONP, however, works differently and will use use the JavaScript parser. Womp womp. The blog post also lists two other cases, although the first case -- parsing JSON using eval -- is both insecure and incorrect. I haven't seen people do that in ages and ages.
- powrtoch 14y agoThat makes sense. I was confused because I was also getting the error when I typed the line into the interpreter by hand. The issue being that I forgot to assign it to a variable (facepalm). Thanks for the explanation.
- mhotchen 14y agoJust an fyi, jQuery's core JSON parser actually uses eval (well, new Function(), which is almost the same, but with scope protection). https://github.com/jquery/jquery/blob/master/src/core.js#L529 https://github.com/jquery/jquery/blob/master/src/core.js#L52...
- rpearl 14y agoI have to comment on this line: > Some libraries implement an unsafe, but fast, JSON parse using “eval” for older browsers eval is not fast! In fact it is the opposite of fast. Most JIT optimizations go away in the face of eval()! Do not use it even if you know it's safe. Use JSON.parse instead.
- shod 14y ago"Older browsers" means those that predate native JSON methods. Libraries often use eval() as a fallback.
- Xion 14y agoThe other thing is that JSON scoffs at trailing comma (both in object and array literals), while JavaScript engines are perfectly happy to accept them.
- troels 14y agoNot all of them are. IE6 will choke.
- martin-adams 14y agoAnd IE7, and IE8.
- masklinn 14y agoIE8 (maybe IE7 as well, not sure anymore) will accept trailing commas in objects. All IE will also "accept" trailing commas in arrays, but they will create a final `undefined` element
- Toshio 14y agoYAML is the new JSON dontcha know.
- wolf81 14y agoInteresting, I should look it up.
- michaelmcmillan 14y agoJudofyr has covered this in depth on his blog: http://timelessrepo.com/json-isnt-a-javascript-subset http://timelessrepo.com/json-isnt-a-javascript-subset