5 ms·
JavaScript's Promise Is Memory Unsafe
- chrismorgan 9y agoI think we’re operating on different definitions of “memory unsafe”. Memory unsafe means accessing uninitialised memory, freed memory, other objects’ memory and so forth. This article seems to simply be describing memory inefficiency in promises, that in certain situations it can leak like a sieve. If Promise in any particular environment was not memory-safe, that would probably be a high or critical security vulnerability. Mere memory leaks are not a security issue. (I’m operating on the reasonable assumption that the JavaScript engine is simply going OOM and crashing for that reason instead of something more sinister.)
- bad_user 9y agoI agree, but I did not know that I can't use "memory unsafe" to describe plain old memory leaks. Indeed, it's not a security issue.
- chrismorgan 9y agoI’m biased by being heavily steeped in Rust, but I believe this is the accepted definition of “memory unsafe”. OOM crashes don’t really get the chance to be memory unsafe—the process is killed, so all its memory vanishes like the dew in the morn, only several orders of magnitude faster.
- deleted 9y ago[deleted]
- skate22 9y agoIs it bad that i read 'OOM' as out of mana?
- vbezhenar 9y agoAs I understood, problem is that stack overflow happens in native code, which causes access violation error and virtual machine is killed. "Proper" stack overflow should result with JavaScript exception and virtual machine should remain in working state, the same is about memory leak.
- chrismorgan 9y agoYeah, that seems a reasonable clarification to put on it: this is more severe than a mere memory leak, because it can be mildly weaponised to a DoS attack. But I expect it’s still only in “bug that would be nice fixed” category rather than “security issue that needs to be fixed”. (Addition: hang on, is this crashing OOM or crashing stack overflow? I’m guessing it’s OOM, in which case it would not be a bug at all.)
- narag 9y ago...which causes access violation error and virtual machine is killed When you write "virtual machine" do you mean the local JavaScript engine? For most people that would be just a little annoyance, the usual browser crash. I actually prefer crash to freeze.
- vbezhenar 9y ago> When you write "virtual machine" do you mean the local JavaScript engine? Yes, of course, JavaScript VM inside a browser process or one of them. > For most people that would be just a little annoyance, the usual browser crash. I actually prefer crash to freeze. Any browser crash is a bug and should never happen for any input. If browser is smart enough to run separate process for different pages, this is little annoyance indeed. I remember when crashed page caused entire browser to crash and often lose open tabs. That wasn't little annoyance. Also some clever guy might figure out how to exploit this crash, I'm not sure if it's possible, but I'm not the clever one :)
- yuchi 9y agoInteresting article but has nothing to do with «Unsafeness». (better wording: Promise implementations leak on the heap)
- sirclueless 9y agoIt's not even a particularly unexpected leak. When you create unbounded recursion, you leak memory. This is true if you don't use Promises, and remains true when you do. This is really just another complaint about lack of Tail-Call Optimization. This issue has come up for any number of languages and libraries. Often I think that the "O" in TCO is a misnomer. If it was really an "Optimization" it wouldn't affect correctness of the program, but there are many cases where a program is correct if TCO is happening but undefined if not. It's more akin to lazy/strict evaluation: equivalent in simple cases, a major correctness issue in more complex ones.
- _nalply 9y agoBut even with Tail-Call Optimisation the code would run forever. In which world is never-terminating hot running code «correct»?
- bad_user 9y agoIn the case where you've got an incoming stream of real time events?
- scarlac 9y ago"Forever" is obviously just a reference to would happen with memory usage. Proper optimized code could run "forever" (or a long time) without increasing in memory usage, ie. memory would scale as O(1) as opposed to O(n).
- bad_user 9y ago> This is really just another complaint about lack of Tail-Call Optimization TCO needs to be supported by the runtime, but what I'm talking about only needs to be supported by the Promise implementation, so in this case it's just a sloppy library we are talking about. > When you create unbounded recursion, you leak memory This is only true in weird universes, like that of JavaScript. It's actually really easy to end up with a really long chain of tail recursive calls - for example when processing streams or when doing functional programming in general. Having to explain why this is a huge problem is one reason for why I feel that JavaScript's ecosystem is so broken. In case you're wondering, given Promise's surprises, I actually think going for the callback hell is saner, because in such cases you just pass a callback around without surprises.
- weddpros 9y agoHis code is creating an infinite promise chain. Did the author really expect it would not eat all his memory and crash? If the author had written the same code with callbacks, a stack overflow would have been thrown. So misunderstanding of promises (and/or async coding) is the problem here, not promises.
- _nalply 9y agoThat's it. It's like a stack overflow. The code contains a function which calls itself via a Promise. There's no guard which will eventually terminate the recursion.
- bad_user 9y ago> His code is creating an infinite promise chain. Did the author really expect it would not eat all his memory and crash? Processing an infinite or really long promise chain is what ends up happening when you're working with streams and functional programming in general. Yes, I expected it to not leak memory, because sane implementations don't leak. One such implementation is Scala's Future [0], using an implementation trick which I then ported in Funfix.org, so it's definitely possible. > If the author had written the same code with callbacks, a stack overflow would have been thrown. That's not true. For one, asynchronous calls will not trigger stack overflows. And a callback approach won't leak heap memory either, because you don't have to return a value-wannabe to the caller, so you're not building a stack. > So misunderstanding of promises (and/or async coding) is the problem here, not promises. I'm involved in no less than 3 libraries [1] [2] [3] implementing Promise and Haskell IO alternatives in JavaScript and Scala, so I'm pretty sure that I understand promises by now :-) I'm also pretty fond of this article I wrote a while back, asynchrony being sort of a fetish of mine: https://alexn.org/blog/2017/01/30/asynchronous-programming-scala.html https://alexn.org/blog/2017/01/30/asynchronous-programming-s... [0] http://www.scala-lang.org/api/2.12.3/scala/concurrent/Future.html http://www.scala-lang.org/api/2.12.3/scala/concurrent/Future... [1] https://monix.io https://monix.io [2] https://github.com/typelevel/cats-effect https://github.com/typelevel/cats-effect [3] https://funfix.org https://funfix.org
- weddpros 9y ago
- bad_user 9y agoArticle has been buried soon after hitting the front page. Given that it has more points and it is newer than some articles on the front page right now, I'm guessing I've hurt people's feelings. As one of its long time visitors and contributors, I am disappointed by HN, but that's not news.
- gotofritz 9y ago~~ hug ~~