ysmood / yaku

A lightweight promise library
https://tonicdev.com/ysmood/yaku
MIT License
291 stars 28 forks source link

Bug: Stealing a resolver and using it to trigger reentrancy #68

Open JakeChampion opened 3 years ago

JakeChampion commented 3 years ago
var Promise = require("yaku");
var assert = require('assert');

var stolenResolver;
var StealingPromiseConstructor = function StealingPromiseConstructor(resolver) {
    stolenResolver = resolver;
    resolver(
        function () {},
        function () {}
    );
};
var iterable = {};
var atAtIterator = '@@iterator'; // on firefox, at least.
iterable[atAtIterator] = function () {
    stolenResolver(null, null);
    throw new Error(0);
};
assert.doesNotThrow(function () {
    Promise.all.call(StealingPromiseConstructor, iterable);
});

It throws this:

AssertionError: Got unwanted exception.
Actual message: "self.reject is not a function"

This test was taken from es6-shim -- https://github.com/paulmillr/es6-shim/blob/4a815033b35a051632e035e1ec95aa3b1b43bfdd/test/promise/simple.js#L34-L51

ysmood commented 3 years ago

@JakeChampion Thank you for your report. Such an edge case, I wonder how you found it?

JakeChampion commented 3 years ago

Im implementing a promise library and ran a big test suite on other promise libraries

ysmood commented 3 years ago

Implementing promise in 2020? For study? 😂

The fix should be easy, but it will decrease the performance a little bit. Other methods like Promise.race also have this bug. I will fix it if I have time. I think people who still use third-party Promise won't care though.