Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2011-10

Stack corruption setting UnicodeString Char

6 messages · 4 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

Usually when we work with PChars we do things like this to set the final terminator:

var
  ansistr: ansistring;
begin
  // Copy the originating string taking into account the specified length
  SetLength(ansistr, len+1);
  System.Move(source^, ansistr[1], len);
  ansistr[len+1] := #0;
  SetLength(ansistr, len);

And it works fine. You get a string with correct length and a final #0 terminator.

Now, I simply tryed the same code for a unicodestring, and it corrupts my stack:

procedure Unicode2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
var
  widestr: unicodestring;
begin
  {$ifdef PASWSTRING_VERBOSE}WriteLn('Unicode2AnsiMove START');{$endif}
  // Copy the originating string taking into account the specified length
  SetLength(widestr, len+1);
  System.Move(source^, widestr[1], len*2);
  PWideChar(@widestr)[len] := #0; // <--- This corrupts the stack
  SetLength(widestr, len);

I already fixed the problem by simply not setting this last widechar to #0, but now I got puzzled: Any ideas why this doesn't work?

It crashes only a bit after this procedure, but I found that this was the statement which caused the problem.

Felipe Monteiro de Carvalho

Reply by email

Sven Barth
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 29 lines
Hello, Usually when we work with PChars we do things like this to set the final terminator: var ansistr: ansistring; begin // Copy the originating string taking into account the specified length SetLength(ansistr, len+1); System.Move(source^, ansistr[1], len); ansistr[len+1] := #0; SetLength(ansistr, len); And it works fine. You get a string with correct length and a final #0 terminator. Now, I simply tryed the same code for a unicodestring, and it corrupts my stack: procedure Unicode2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt); var widestr: unicodestring; begin {$ifdef PASWSTRING_VERBOSE}WriteLn('Unicode2AnsiMove START');{$endif} // Copy the originating string taking into account the specified length SetLength(widestr, len+1); System.Move(source^, widestr[1], len*2); PWideChar(@widestr)[len] := #0; //<--- This corrupts the stack SetLength(widestr, len);

Why don't you use the same statement as for the AnsiString version?

E.g.

widestr[len+1] := #0;

Regards,
Sven

Reply by email

Tomas Hajny
to Felipe Monteiro de Carvalho: Usually when we work with PChars we do things like this to set the final terminator: var…

On Wed, October 19, 2011 09:13, Felipe Monteiro de Carvalho wrote:

Hi,

Show quoted text 35 lines
Usually when we work with PChars we do things like this to set the final terminator: var ansistr: ansistring; begin // Copy the originating string taking into account the specified length SetLength(ansistr, len+1); System.Move(source^, ansistr[1], len); ansistr[len+1] := #0; SetLength(ansistr, len); And it works fine. You get a string with correct length and a final #0 terminator. Now, I simply tryed the same code for a unicodestring, and it corrupts my stack: procedure Unicode2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt); var widestr: unicodestring; begin {$ifdef PASWSTRING_VERBOSE}WriteLn('Unicode2AnsiMove START');{$endif} // Copy the originating string taking into account the specified length SetLength(widestr, len+1); System.Move(source^, widestr[1], len*2); PWideChar(@widestr)[len] := #0; // <--- This corrupts the stack SetLength(widestr, len); I already fixed the problem by simply not setting this last widechar to #0, but now I got puzzled: Any ideas why this doesn't work? It crashes only a bit after this procedure, but I found that this was the statement which caused the problem.

Sorry for a silly question, but why the difference between the two implementations (i.e. why not addressing the WideStr element directly without the typecast)? Moreover, even if using the PWideChar, I believe that the correct version would be without the '@' (i.e.: PWideChar(widestr)[len] := #0), wouldn't it?

Tomas

Reply by email

Mattias Gaertner
to Felipe Monteiro de Carvalho: Usually when we work with PChars we do things like this to set the final terminator: var…

Felipe Monteiro de Carvalho hat am 19.
Oktober 2011 um 09:13 geschrieben:

Show quoted text 16 lines
Hello, Usually when we work with PChars we do things like this to set the final terminator: var    ansistr: ansistring; begin    // Copy the originating string taking into account the specified length    SetLength(ansistr, len+1);    System.Move(source^, ansistr[1], len);    ansistr[len+1] := #0;    SetLength(ansistr, len); And it works fine. You get a string with correct length and a final #0 terminator. 

I never saw such code for ansistring. Only for shortstring.  SetLength(ansistring) already allocates memory for the header+len+1, creates the header and sets the len+1 character to #0. 
Simply do:
  SetLength(ansistr, len);
  if len>1 then
    System.Move(source^, ansistr[1], len);
 

Show quoted text 13 lines
Now, I simply tryed the same code for a unicodestring, and it corrupts my stack: procedure Unicode2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt); var    widestr: unicodestring; begin    {$ifdef PASWSTRING_VERBOSE}WriteLn('Unicode2AnsiMove START');{$endif}    // Copy the originating string taking into account the specified length    SetLength(widestr, len+1);    System.Move(source^, widestr[1], len*2);    PWideChar(@widestr)[len] := #0; // <--- This corrupts the stack 

This would corrupt the stack for ansistring too. This would only work for shortstring.
widestr is a unicodestring is a pointer to widechar.    
  PWideChar(widestr)[len] := #0; 
 
 

Show quoted text 6 lines
   SetLength(widestr, len);> I already fixed the problem by simply not setting this last widechar to #0, but now I got puzzled: Any ideas why this doesn't work? It crashes only a bit after this procedure, but I found that this was the statement which caused the problem.

Mattias

Reply by email

Felipe Monteiro de Carvalho
to Tomas Hajny: Sorry for a silly question, but why the difference between the two implementations (i.e.…

2011/10/19 Tomas Hajny :

Sorry for a silly question, but why the difference between the two implementations (i.e. why not addressing the WideStr element directly without the typecast)?

Actually it should be a pointer operation in the ansistring version too, because setting chars in a string calls UniqueString, which is undesirable and inneficient.

Moreover, even if using the PWideChar, I believe that the correct version would be without the '@' (i.e.: PWideChar(widestr)[len] := #0), wouldn't it?

Good idea! I think you found the problem.

Felipe Monteiro de Carvalho

Reply by email