Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/RTL/Delphi/Other RTL    [ Add a report in this area ]  
Report #:  104692   Status: Closed
[Regression in XE2] Error on calling dispinterface method when passing empty WideString value as parameter.
Project:  Delphi Build #:  16.0.4429.46931
Version:    16.4 Submitted By:   Kenjiro Fukumitsu
Report Type:  Crash / Data loss / Total failure Date Reported:  4/6/2012 3:22:54 AM
Severity:    Critical / Show Stopper Last Updated: 9/5/2012 7:52:53 PM
Platform:    All versions Internal Tracking #:   28221
Resolution: Fixed (Resolution Comments) Resolved in Build: : 17.0.4625.53395
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: 10
Description
If you pass an empty string to WideString as parameter of dispinterface method, an invalid string has been passed.

There must be some problem in System.Win.ComObj.DispCallByID.

This problem does not happen with Delphi XE.
Steps to Reproduce:
1. Compile attached sample program and debug it to confirm this issue.

2. Set break point at entrance of this function.
---------------------
  IDispTestDisp = dispinterface
    ['{D00382F6-24FC-4127-A388-491607885920}']
    procedure TestProc(const Param1: WideString; const Param2: WideString; const Param3: WideString); dispid 1;
  end;
---------------------
---------------------
procedure TDispTestImpl.TestProc(const Param1, Param2, Param3: WideString);
var
  sl : TStringList;
begin // <<-- add breakpoint here
  sl := TStringList.Create;
  try
    sl.Add( IntToStr(Length(Param1)) );
    sl.Add( Param1 );
    sl.Add( IntToStr(Length(Param2)) );
    sl.Add( Param2 );
    sl.Add( IntToStr(Length(Param3)) );
    sl.Add( Param3 );

    ShowMessage( sl.Text );
  finally
    sl.Free;
  end;
end;

procedure TForm79.Button1Click(Sender: TObject);
var
  p1, p2, p3 : WideString;
begin
  p1 := 'abcdef';
  p2 := '??????????';
  p3 := '';

  FDispTest.TestProc( p1, p2, p3 );
end;

procedure TForm79.FormCreate(Sender: TObject);
var
  idisp : IDispTest;
  typelib : ITypeLib;
  fname : WideString;
begin
  SetLength(fname, MAX_PATH);
  GetModuleFileName( hInstance, PWideChar(fname), Length(fname));
  fname := fname + '\1';
  typelib := LoadTypeLibrary( PWideChar( fname ));
  idisp := TDispTestImpl.Create( typelib, IID_IDispTest );
  FDispTest := idisp as IDispTestDisp;
end;
---------------------

3. When process stopped at the break point, move cursor to "Param3" variable.
Variable tooltip shows unexpected string.

Expected: Empty string.
Actual: Very long binary data starting with #0#0.

This is NOT a debugger issue.
If you give empty string to dispinterface method, sometimes exception occurs(Out of memory), sometimes doesn't.

Note:
  This problem does not happen with non-empty string.
Workarounds
None
Attachment
DispCallTest.zip
Comments

Tomohiro Takahashi at 4/6/2012 8:29:17 PM -
> This problem does not happen with XE2.
Could you tell us more detail about it?
What version of Delphi should we use to reproduce/confirm your issue?

> 3. When process stopped at the break point, move cursor to "Param3" variable.
Is your issue about Debugger?
and, what result do you get?
  Expected: ?
  Actual: ?

Kenjiro Fukumitsu at 4/8/2012 10:37:26 PM -
>> This problem does not happen with XE2.
> Could you tell us more detail about it?
> What version of Delphi should we use to reproduce/confirm > your issue?

Sorry, this was incorrect.
This problem does not happen with XE.
I confirmed this issue with XE2.

> 3. When process stopped at the break point, move cursor > > to "Param3" variable.
> Is your issue about Debugger?
> and, what result do you get?
>   Expected: ?
>   Actual: ?

Variable tooltip shows unexpected string.

Expected: Empty string.
Actual: Very long binary data starting with #0#0.

This is not a debugger issue.
If you give empty string to dispinterface method, sometimes exception occurs(Out of memory), sometimes doesn't.

Tomohiro Takahashi at 4/9/2012 6:54:04 AM -
I modified [Title], [Description], and [Steps] field as Sysop.
Thanks.

Robert Ogren at 5/4/2012 12:01:44 AM -
I'm seeing this problem as well, in Delphi XE2 Update 4. It especially happens when using TClientDataSet with midaslib and not having midas.dll installed on the client so that TDispatchAppServer is used, resulting in the error message "CommandText changes are not allowed" because the CommandText, which is supposed to be empty, is sent as a long string of garbage to the application server. Report 103983 may therefore be caused by the issue described in this report.


As far as I can see, the problem is in System.Variants, function GetDispatchInvokeArgs, this line:

        varOleStr:    PVarParm^.VPointer := PWideChar(PWideString(Params)^);


If the string is empty, _WStrToPWChar will return a pointer to a null character, but this is not a valid BSTR as that is supposed to have length information before the string much like Delphi strings. The bytes that happen to be before the EmptyString constant is treated as the string length. The code for other cases in GetDispatchInvokeArgs, such as atString and atUString, has special handling for empty strings.

If necessary, I can provide another simple test case.

Tomohiro Takahashi at 5/17/2012 7:32:28 PM -
This report was opened with valid Internal Tracking Number.
Thanks.

Guy Glirbas at 10/30/2012 4:16:35 PM -
For people hitting this issue, we are tyring this work around fix to Dtasnap.Provider:

procedure TDataSetProvider.SetCommandText(const CommandText: WideString);
begin
  if CommandText = '' then Exit;
  if CommandText[1] = #0 then Exit; // <-----   Work Around
  if not (poAllowCommandText in Options) then
    DatabaseError(SCannotChangeCommandText);
  CheckDataSet;

  (DataSet as IProviderSupport).PSSetCommandText(CommandText);
end;

Guy Glirbas at 10/31/2012 12:07:30 PM -
This issue is nastier than I first thought.  These empty strings with non zero length cause bad memory issues for our application.  Delphi libraries that copy strings aften allocate memory based on the length bytes preceding strings.  Our application does not work with XE2. We get out of memory errors and access viloations.  Will a hot fix be available or must we upgrade to XE3 to get the fix?

Server Response from: ETNACODE01