Thread overview
[Issue 8563] New: Exception segfault
Aug 20, 2012
Daniel Cousens
Feb 18, 2013
Maxim Fomin
Feb 18, 2013
Maxim Fomin
Feb 18, 2013
Maxim Fomin
Jun 27, 2013
Nils
Jun 27, 2013
Nils
Jul 02, 2013
Kenji Hara
Jul 02, 2013
Maxim Fomin
August 20, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8563

           Summary: Exception segfault
           Product: D
           Version: D2
          Platform: x86_64
        OS/Version: All
            Status: NEW
          Severity: critical
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: daniel350@bigpond.com


--- Comment #0 from Daniel Cousens <daniel350@bigpond.com> 2012-08-20 03:12:35 PDT ---
http://dpaste.dzfl.pl/08d60e83

import std.exception : assertThrown;
import std.file : dirEntries, SpanMode;

// segfault does not occur with -O command line argument (exception is thrown
as expected with -O)
void main() {
      assertThrown(dirEntries("test", SpanMode.breadth)); // assert does not
fail, as expected (ie, exception was thrown)
      func("test");
}

void func(string suicide_variable) { // must be in a seperate function
      auto ax = suicide_variable; // uncomment this for a segfault in the
following statement
                                  // not clear as to why, can't yet reproduce
with other unpredictable exceptions (AFAIK)

      foreach(s; dirEntries("test", SpanMode.breadth)) {} // exception is
expected, not a segfault
}

----------

I tried to produce this behaviour for other functions (ie, without the dirEntries call), but I could not get at it; but this is all still very much undefined behaviour.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 18, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=8563


Maxim Fomin <maxim@maxim-fomin.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |maxim@maxim-fomin.ru


--- Comment #1 from Maxim Fomin <maxim@maxim-fomin.ru> 2013-02-18 09:06:35 PST ---
Reduced

struct DirEntry
{
    string name;
}

struct DirIteratorImpl
{
    DirEntry _cur;
    @property bool empty(){  return true; }
    @property DirEntry front(){ return _cur; }
    void popFront() { }
}

struct RefCounted
{
    struct RefCountedStore
    {
        private struct Impl
        {
            DirIteratorImpl _payload;
            size_t _count;
        }

        private Impl* _store;

    }
    RefCountedStore _refCounted;

    ~this()
    {
        if (_refCounted._store)
            _refCounted._store._count = 0;
    }

    ref inout(DirIteratorImpl) refCountedPayload() inout
    {
        if (_refCounted._store)
            return _refCounted._store._payload;
        else
            throw new Exception("absent");
    }
    alias refCountedPayload this;
}

struct DirIterator
{
    RefCounted impl;
    this(string pathname)
    {
        throw new Exception("");
    }
    @property bool empty(){ return impl.empty; }
    @property DirEntry front(){ return impl.front; }
    void popFront(){ impl.popFront(); }
}

auto dirEntries(string path)
{
    return DirIterator(path);
}

void main() {
      foreach(s; dirEntries("test")) {}
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 18, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=8563



--- Comment #2 from Maxim Fomin <maxim@maxim-fomin.ru> 2013-02-18 11:03:57 PST ---
Further reduced:

struct Foo
{
    int[100] i;
}

struct DirIterator
{
    Foo* _store ;

    ~this()
    {
        if (_store)
        {
            _store.i = 0; // to segfault for sure
            _store = null;
        }
    }
    this(string pathname)
    {
        throw new Exception("");
    }
    void popFront() { }
    bool empty()  { return true; }
    Foo front() { return *_store; }
}

auto dirEntries()
{
    return DirIterator("path");
}

void main() {
    foreach(s; dirEntries()) {}
}

This looks like issue 9438 (struct with pointer field and dtor) but now temporaries from function return values are involved.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 18, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=8563



--- Comment #3 from Maxim Fomin <maxim@maxim-fomin.ru> 2013-02-18 11:26:46 PST ---
The reason of the issue seems to be in that struct temporary inside main() is not initialized. If, line

foreach(s; dirEntries()) {}

is replaced to directly accessing object

foreach(s; DirIterator("path")) {}

dmd emits some code to clear the stack before assigning $rdi.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 27, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=8563


Nils <nilsbossung@googlemail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |nilsbossung@googlemail.com


--- Comment #4 from Nils <nilsbossung@googlemail.com> 2013-06-26 19:07:23 PDT ---
*** Issue 10475 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 27, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=8563



--- Comment #5 from Nils <nilsbossung@googlemail.com> 2013-06-26 19:09:12 PDT ---
Some observations (includes the stuff form issue 10475):

struct DirIterator
{
    int _store = 42;
    this(string dummy) {throw new Exception("constructor");}
    ~this()
    {
        assert(_store == 42, "destructing garbage");
        assert(false, "destructor");
    }
}

DirIterator dirEntries() {return DirIterator("");}

void main()
{
    /* This triggers only "constructor". The destructor is not called. */
    version(A) DirIterator a = dirEntries();

    /* This triggers "constructor" and "destructing garbage".
    I.e. destructor is called on uninitialized data. Probably fine in this case
    because of explicit void initialization. */
    else version(B)
    {
        DirIterator b = void;
        b = dirEntries();
    }

    /* This triggers "constructor" and "destructor".
    Arguably, the destructor should not be called, since construction has
    failed. */
    else version(C) for(DirIterator c = DirIterator(""); true; ) {}

    /* Just like B, this triggers "constructor" and "destructing garbage".
    No explicit void initialization here, so that should not happen. */
    else version(D) for(DirIterator c = dirEntries(); true;) {}

    else static assert(false);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
July 02, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=8563



--- Comment #6 from Kenji Hara <k.hara.pg@gmail.com> 2013-07-02 07:05:14 PDT ---
I posted bug 10475 fix and now it's merged in git head. Could you please confirm the actual case by using git head?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
July 02, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=8563


Maxim Fomin <maxim@maxim-fomin.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED


--- Comment #7 from Maxim Fomin <maxim@maxim-fomin.ru> 2013-07-02 10:12:24 PDT ---
(In reply to comment #6)
> I posted bug 10475 fix and now it's merged in git head. Could you please confirm the actual case by using git head?

This issue is also fixed. Thank you.

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