Check out Dart's iterators

Claude Pache claude.pache at gmail.com
Sun Feb 10 18:35:29 PST 2013


Le 10 févr. 2013 à 22:01, David Bruant <bruant.d at gmail.com> a écrit :

> <snip>
> 
> I have to note that there is a minor security hazard in code using iterators naively:
>    import process from "m";
> 
>    var a = [1, 2, 3, 4, 5];
>    var next = 0;
>    var it = {
>        next: function(){
>            if(next < a.length){
>                // If the call to "process" throws StopIteration because it's malicious/buggy,
>                // so does this code and that's largely unexpected.
>                return process(a[next++]);
>            }
>            else{
>                throw StopIteration;
>            }
>        }
>    }
> 
> You can always protect yourself by wrapping the call to "process" with a try/catch block.
> <snip>


Note that the same issue arises with generators:

	function* gen(a) {
		var next = 0;
		if (next < a.length) {
			// the iterator will end prematurely if "process" throws a StopIteration
			yield process(a[next++]);
		}
	}

In order to mitigate the problem, instead of throwing a generic StopIteration, I think we ought to throw a specific StopIteration instance with information on which iterator has thrown. More precisely, inside a generator function, a return statement will throw a StopIteration instance with its "source" property set to the generator iterator which was terminated.

For manually throwing a StopIteration from inside a "next" method of an iterator, we could use:

	throw new StopIteration(this)

And instead of "e instanceof StopIteration", we may use a more precise check:

    e instanceof StopIteration && e.source === it


—Claude


More information about the es-discuss mailing list