www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 6175] New: String corruption when passing static char arrays to std.conv

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175

           Summary: String corruption when passing static char arrays to
                    std.conv
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Severity: major
          Priority: P2
         Component: Phobos
        AssignedTo: nobody puremagic.com
        ReportedBy: andrej.mitrovich gmail.com



10:18:57 PDT ---
This is fairly odd behavior:

Case 1:
char[9] statCArr = "blablabla";
auto res1 = to!(char[])(statCArr);    

writeln(res1);          // writes M  
writeln(statCArr[]);    // writes blablabla

Case 2:
char[9] statCArr = "blablabla";
auto res1 = to!(char[])(statCArr);    

writeln(res1);          // writes L  
writeln(statCArr);    // writes blablabla

Note: I've only removed the square brackets and this somehow ends up changing
the garbage value of res1. You can add random writeln() statements before the
call to std.conv.to and res would get different results.

If you reduce the character count then you get a compile time error:

char[6] statCArr = "blabla";
auto res2 = to!(char[])(statCArr);

D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(99): Error: template
std.conv.toImpl(T,S) if (!implicitlyConverts!(S,T) && isSomeString!(T) &&
isInputRange!(Unqual!(S)) &&
isSomeChar!(ElementType!(S))) toImpl(T,S) if (!implicitlyConverts!(S,T) &&
isSomeString!(T) && isInputRange!(Unqual!(S)) && isSomeChar!(ElementType!(S)))
matches more than one
template declaration,
D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(231):toImpl(T,S) if
(isStaticArray!(S)) and
D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(566):toImpl(Target,Source)
if (implicitlyConverts!(Source,Target))

So std.conv.to is pretty buggy for static arrays..

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 18 2011
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175




10:29:12 PDT ---
I've noticed this while trying to add some additional capability to
std.conv.to. In particular, I've added returning static arrays, and accepting
wchar* and not just char* and converting that to some string/char[] type. Maybe
I could have a go at fixing this too..

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 18 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175




07:17:05 PST ---
This has now changed to a template error:

import std.conv;

void main()
{
    char[9] statCArr = "blablabla";
    auto res1 = to!(char[])(statCArr);
}

D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(237): Error: template
std.conv.toImpl(T,S) if (isImplicitlyConvertible!(S,T)) toImpl(T,S) if
(isImplicitlyConvertible!(S,T)) matches more than one template declaration,
D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(245):toImpl(T,S) if
(isImplicitlyConvertible!(S,T)) and
D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(350):toImpl(T,S) if
(isStaticArray!(S))

A simple workaround is to pass a slice:
    auto res1 = to!(char[])(statCArr[]);

But since to() seems to have specializations for static arrays I'll leave this
open.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 04 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175




19:46:30 PDT ---

 This has now changed to a template error:
 
 import std.conv;
 
 void main()
 {
     char[9] statCArr = "blablabla";
     auto res1 = to!(char[])(statCArr);
 }
And now in 2.058 it has reverted back to buggy behavior again: import std.conv; import std.stdio; void main() { char[9] statCArr = "blablabla"; auto res1 = to!(char[])(statCArr); writeln(res1); } $ rdmd test.d $ B -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175


SomeDude <lovelydear mailmetrash.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lovelydear mailmetrash.com



PDT ---
Isn't it the normal behaviour ?
If statCArr is declared const or immutable, it works as intended.

import std.conv, std.stdio;

void main()
{
    immutable char[9] statCArr = "BlaBlaBla";
    writeln("poupoupidouwah");
    auto res1 = to!(char[])(statCArr);
    writeln(res1);
    writeln(statCArr[]);
}


PS E:\DigitalMars\dmd2\samples> rdmd bug.d
poupoupidouwah
BlaBlaBla
BlaBlaBla
PS E:\DigitalMars\dmd2\samples>

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 19 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com



07:44:51 PDT ---

 import std.conv, std.stdio;
 
 void main()
 {
     immutable char[9] statCArr = "BlaBlaBla";
     writeln("poupoupidouwah");
     auto res1 = to!(char[])(statCArr);
     writeln(res1);
     writeln(statCArr[]);
 }
This is converting const, so to is likely doing a dup/idup. If you change res1 to immutable(char)[], it fails in the same way. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 19 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175




08:01:06 PDT ---
Interesting problem!

So here is what happens.  The IFTI type determined for the statCArr argument is
char[9u], which means it's actually passed as a static array *by value*.

The first toImpl template matches and it looks like this:

/**
If the source type is implicitly convertible to the target type, $(D
to) simply performs the implicit conversion.
 */
T toImpl(T, S)(S value)
    if (isImplicitlyConvertible!(S, T))
{
    alias isUnsigned isUnsignedInt;

    // Conversion from integer to integer, and changing its sign
    static if (isUnsignedInt!S && isSignedInt!T && S.sizeof == T.sizeof)
    {   // unsigned to signed & same size
        enforce(value <= cast(S)T.max,
                new ConvOverflowException("Conversion positive overflow"));
    }
    else static if (isSignedInt!S && isUnsignedInt!T)
    {   // signed to unsigned
        enforce(0 <= value,
                new ConvOverflowException("Conversion negative overflow"));
    }

    return value;
}

Both of those static ifs fail, so it essentially boils down to this:

char[] toImpl(char[9u] value)
{
   return value;
}

this means it is returning stack data!  I'm surprised this is allowed to
compile, I though the compiler would disallow such obvious escaping of stack
data.

I suppose the "correct" fix is to return value.dup in this case, but I hate the
idea that the entire array is passed on the stack, seems wasteful.

Someone with better template-fu skills than me should tackle this...

BTW, what do we think the "correct" implementation *should* be?  .dup the array
or return a slice of the original?  I don't know if slicing is possible given
IFTI limitations.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 19 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull, wrong-code



https://github.com/D-Programming-Language/phobos/pull/575

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 12 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175




Commit pushed to master at https://github.com/D-Programming-Language/phobos

https://github.com/D-Programming-Language/phobos/commit/8d455147cfa35bd514796dfc008ee67142213777
fix Issue 6175 - String corruption when passing static char arrays to std.conv

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 22 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6175


Kenji Hara <k.hara.pg gmail.com> changed:

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


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