Bug 2975 – copy - source may exceed target

Status
RESOLVED
Resolution
WONTFIX
Severity
minor
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2009-05-13T12:55:00Z
Last change time
2015-06-09T01:27:58Z
Keywords
patch
Assigned to
bugzilla
Creator
k-foley

Comments

Comment #0 by k-foley — 2009-05-13T12:55:33Z
Here is the current copy: Range2 copy(Range1, Range2)(Range1 source, Range2 target) if (isInputRange!(Range1) && isOutputRange!(Range2, ElementType!(Range1))) { foreach (e; source) { target.put(e); } return target; } When source has more elements than the target, it's possible to raise an exception once target.empty is true. I am unsure whether this is intended behavior. Here is what I think it should be: Range2 copy(Range1, Range2)(Range1 source, Range2 target) if (isInputRange!(Range1) && isOutputRange!(Range2, ElementType!(Range1))) { while ( !source.empty && !target.empty ) { target.put( source.front ); source.popFront(); } return target; } Is there a good reason to let copy proceed once target is exhausted?
Comment #1 by andrej.mitrovich — 2011-05-26T13:21:31Z
This will be caught in non-release builds, simply because copy calls put(), which calls front(target), where front() has this assert: assert(a.length, "Attempting to fetch the front of an empty array"); The assert goes away in release, which means if you compile the following with -release the enforce will pass since memory will get overwritten: import std.algorithm; import std.exception; void main() { // compile with -release auto a = [1, 2, 3, 4, 5]; int[] b = new int[3]; copy(a, b); enforce(b[3] == 4); // oops.. } If we add your changes it means debug builds will end up doing double checks, once in copy() where it would check for "!target.empty" (which I think should actually be expression "target.length"), and once in the call to front() by the put() function. I'm not sure what, if anything should be done about this. Personally I would only expect the possibility of this kind of memory corruption if I pass the -noboundscheck switch. Anyone else care to share their opinion?
Comment #2 by issues.dlang — 2011-05-26T14:22:25Z
Output ranges only require the put function. You can't enquire about their length or whether they're empty - not unless you're relying on them being something more specific than just an output range. It's up to the output range to decide how it deals with calls to put that it can't handle. And it's up to the caller of copy to make sure that the target has enough space. copy does not explicitly check and _can't_ check, because output ranges don't give it that ability.