Skip to content

Fix Win64 type mismatch in IDataObject.HasFormat#292

Open
csm101 wants to merge 4 commits intoTurboPack:masterfrom
csm101:master
Open

Fix Win64 type mismatch in IDataObject.HasFormat#292
csm101 wants to merge 4 commits intoTurboPack:masterfrom
csm101:master

Conversation

@csm101
Copy link
Copy Markdown

@csm101 csm101 commented Mar 29, 2026

Here the code was passing a pointer to a NativeInt variable (which can be either a 32 or 64 bit integer) to a function that explicitly expects a pointer to a LongInt variable (32 bit) regardless of the architecture

The COM API signature is Next(celt, out rgelt, pceltFetched: PLongint), so passing @returned where Returned was NativeInt produced an incompatible types error (PLongInt vs Pointer) on strict Win64 builds.

I noticed it only because I included this unit in a project where i did enable more strict type pointer checking for the @ operator, and it became a compilation error

csm101 added 2 commits March 29, 2026 18:52
Use a Longint variable for IEnumFORMATETC.Next pceltFetched output.

The COM API signature is Next(celt, out rgelt, pceltFetched: PLongint), so passing @returned where Returned was NativeInt produced an incompatible types error (PLongInt vs Pointer) on strict Win64 builds.

This change makes the argument type match the API contract exactly.
Use a Longint variable for IEnumFORMATETC.Next pceltFetched output.

The COM API signature is Next(celt, out rgelt, pceltFetched: PLongint), so passing @returned where Returned was NativeInt produced an incompatible types error (PLongInt vs Pointer) on strict Win64 builds.

This change makes the argument type match the API contract exactly.
Copilot AI review requested due to automatic review settings March 29, 2026 17:08
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Win64 strict-pointer type mismatch in HasFormat by aligning the local pceltFetched variable type with the COM IEnumFORMATETC.Next signature (which expects PLongint).

Changes:

  • Update Returned from NativeInt to Longint so @Returned matches PLongint on strict Win64 builds.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@csm101
Copy link
Copy Markdown
Author

csm101 commented Mar 29, 2026

I have added another unrelated bugfix for a more serious issue: the syntax highlighter for Delphi has a bug in the code supporting the new syntax for multiline string literals (those enclosed by '''/''') that can make it enter into an endless loop for some malformed strings.
I got into an endless loop myself by trying to feed the syntax highlighter with the output of "cvs annotate" (equivalent of git blame for cvs) for a pascal source of mine.

this is a DUnitX unit test reproducing the issue:

unit TestSynHighlighterDelphi;

interface

uses
  DUnitX.TestFramework,
  SynHighlighterDelphi;

type
  [TestFixture]
  TTestSynDelphiSynInfiniteLoop = class
  private
    procedure AssertLineScansWithoutHang(AHighlighter: TSynDelphiSyn;
      const ALine: string; ALineNumber: Integer);
  public
    [Test] procedure Next_MultilineStringRange_AdvancesRunToEol;
    [Test] procedure Next_EmptyLineInMultilineStringRange_AdvancesRunToEol;
    [Test] procedure Next_MultilineStringDelimiterLine_DoesNotHang;
    [Test] procedure Next_AnnotateStyleLineWithTripleQuote_AdvancesRunToEol;
  end;

implementation

uses
  System.SysUtils;

procedure TTestSynDelphiSynInfiniteLoop.AssertLineScansWithoutHang(
  AHighlighter: TSynDelphiSyn; const ALine: string; ALineNumber: Integer);
const
  MAX_ITERATIONS = 100000;
var
  LIterations: Integer;
  LPrevTokenPos: NativeInt;
begin
  AHighlighter.SetLine(ALine, ALineNumber);
  LIterations := 0;

  while not AHighlighter.GetEol do
  begin
    LPrevTokenPos := AHighlighter.GetTokenPos;
    AHighlighter.Next;
    Inc(LIterations);

    if (AHighlighter.GetTokenPos = LPrevTokenPos) and not AHighlighter.GetEol then
      Assert.Fail(Format('Tokenizer stopped advancing at line %d. TokenPos=%d, Text="%s"',
        [ALineNumber, LPrevTokenPos, ALine]));

    if LIterations > MAX_ITERATIONS then
      Assert.Fail(Format('Potential infinite loop at line %d. Iterations=%d, TokenPos=%d, Len=%d',
        [ALineNumber, LIterations, AHighlighter.GetTokenPos, Length(ALine)]));
  end;
end;

procedure TTestSynDelphiSynInfiniteLoop.Next_MultilineStringRange_AdvancesRunToEol;
var
  LHighlighter: TSynDelphiSyn;
begin
  LHighlighter := TSynDelphiSyn.Create(nil);
  try
    LHighlighter.ResetRange;
    AssertLineScansWithoutHang(LHighlighter, 'x := ' + #39#39#39, 0);
    AssertLineScansWithoutHang(LHighlighter, 'body line', 1);
  finally
    LHighlighter.Free;
  end;
end;

procedure TTestSynDelphiSynInfiniteLoop.Next_EmptyLineInMultilineStringRange_AdvancesRunToEol;
var
  LHighlighter: TSynDelphiSyn;
begin
  LHighlighter := TSynDelphiSyn.Create(nil);
  try
    LHighlighter.ResetRange;
    AssertLineScansWithoutHang(LHighlighter, 'x := ' + #39#39#39, 0);
    AssertLineScansWithoutHang(LHighlighter, '', 1);
  finally
    LHighlighter.Free;
  end;
end;

procedure TTestSynDelphiSynInfiniteLoop.Next_MultilineStringDelimiterLine_DoesNotHang;
var
  LHighlighter: TSynDelphiSyn;
begin
  LHighlighter := TSynDelphiSyn.Create(nil);
  try
    LHighlighter.ResetRange;
    AssertLineScansWithoutHang(LHighlighter, 'x := ' + #39#39#39, 0);
    AssertLineScansWithoutHang(LHighlighter, 'body line', 1);
    AssertLineScansWithoutHang(LHighlighter, #39#39#39, 2);
    Assert.AreEqual<NativeUInt>(NativeUInt(Pointer(rsMultilineString)),
      NativeUInt(LHighlighter.GetRange));
  finally
    LHighlighter.Free;
  end;
end;

procedure TTestSynDelphiSynInfiniteLoop.Next_AnnotateStyleLineWithTripleQuote_AdvancesRunToEol;
var
  LHighlighter: TSynDelphiSyn;
begin
  LHighlighter := TSynDelphiSyn.Create(nil);
  try
    LHighlighter.ResetRange;
    AssertLineScansWithoutHang(LHighlighter,
      '1.10     (user   01-Jan-24): S := ' + #39#39#39, 0);
    AssertLineScansWithoutHang(LHighlighter,
      '1.10     (user   01-Jan-24): hello world', 1);
  finally
    LHighlighter.Free;
  end;
end;

end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants