[Issue 14485] .front of empty filtered zip range is accessible

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Thu Apr 23 22:03:39 PDT 2015


https://issues.dlang.org/show_bug.cgi?id=14485

--- Comment #3 from Jonathan M Davis <issues.dlang at jmdavisProg.com> ---
(In reply to Vladimir Panteleev from comment #2)
> The suspicious combination of things needed to reproduce this bug makes it
> suspicious, though my test case might be reducible a bit.

Hmmm. Well, the fact that the code doesn't throw or blow up isn't particularly
suspicious. It's quite possible that it would just return the last value for
front for an inner range. However, digging through the code, the code for zip
is a bit weird. filter doesn't do any checks in front, and iota asserts that
the range is non-empty in its front, but zip has a function which seems to
return the init value of its element type if the range is empty, which seems
quite weird, but it probably has to do with how zip handles ranges of differing
lengths (I don't use zip much, so I don't remember how it's supposed to handle
that).

So, exactly what zip is doing when you call front when it's empty seems a bit
weird, but it's a bug whenever you do that, so I'm not sure that zip is really
doing anything wrong (though arguably it would be better if it threw a
RangeError just so that the bug gets caught).

> But even if what you say is true, is there a function in Phobos which checks
> "empty", returns "front" if false, and throws if true?

Not that I'm aware of. Some ranges assert in front and popFront that the range
isn't empty, others throw a RangeError, and others don't check at all - though
I think that this idiom has been increasingly used:

    version(assert) if (empty) throw new RangeError();

so that it's halfway between asserting and just throwing a RangeError.

Code is supposed to check empty before it calls front or popFront; and IIRC,
one of the last newsgroup discussions on that concluded that in the general
case, you _had_ to call empty before calling front or popFront even if you knew
that the range was non-empty, because some ranges do work in empty. :|

So, your code is clearly buggy in that it's calling front without having called
empty first, and while how the ranges in question handle that isn't necessarily
as clean as it should be, it's not technically wrong either.

And since it's normally considered a logic bug in a program if it doesn't check
empty before calling front or popFront on a range, I'm not sure how much sense
it makes to have a function which takes a range, checks empty, and then throws
if it's true and returns front if it's not.

--


More information about the Digitalmars-d-bugs mailing list