Thread overview
[Issue 2975] New: copy - source may exceed target
May 13, 2009
k-foley@onu.edu
May 26, 2011
Andrej Mitrovic
May 26, 2011
Jonathan M Davis
May 13, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2975

           Summary: copy - source may exceed target
           Product: D
           Version: 2.030
          Platform: All
        OS/Version: All
            Status: NEW
          Keywords: patch
          Severity: minor
          Priority: P2
         Component: Phobos
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: k-foley@onu.edu


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?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=2975


Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich@gmail.com


--- Comment #1 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2011-05-26 13:21:31 PDT ---
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?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=2975


Jonathan M Davis <jmdavisProg@gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |jmdavisProg@gmx.com
         Resolution|                            |WONTFIX


--- Comment #2 from Jonathan M Davis <jmdavisProg@gmx.com> 2011-05-26 14:22:25 PDT ---
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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------