AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi TStringList verhält sich in D11 anders mit enthaltenen #0
Thema durchsuchen
Ansicht
Themen-Optionen

TStringList verhält sich in D11 anders mit enthaltenen #0

Ein Thema von Rolf Frei · begonnen am 25. Aug 2022 · letzter Beitrag vom 12. Sep 2022
Antwort Antwort
Rolf Frei

Registriert seit: 19. Jun 2006
629 Beiträge
 
Delphi 11 Alexandria
 
#1

TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 25. Aug 2022, 01:07
Delphi-Version: 11 Alexandria
Habe eben einen unschönen Bug (oder Absicht?) in der TSrtingList, genauer in TString.SetTextStr, gefunden, den es in 10.3 noch nicht gab. Im konkreten Fall lade ich ein HTML-Template in eine TStringList (TPageProducer.HTMLDoc.LoadFormFile(..)). Nun hat sich hier ein Template eingeschlichen das anscheinend seit Jaharen ein #0 Char ehthalten hat. Diese war bisher keien Problem, da die StringList solche #0 (und #13#10) bisher überlesen hat.

Das Problem ist nun, dass enthaltene #0 Character in D11 nicht mehr herausgefiltert werden, sondern im SL.Text enthalten bleiben. Das hat nun den Nebeneffekt das der TPageProducer.Content nicht mehr das ganze Template verabeitet und alles nach dem #0 fehlt. Das #0 ist für den Parser im TPageProducer eine Fileende.

Mich würde nun interessieren, wieso TString.SetTextStr komplett umgeschrieben wurde und die #0 Zeichen nicht mehr behandelt. Ist das Absicht oder eine Bug?

Code aus D10.3:
Delphi-Quellcode:
procedure TStrings.SetTextStr(const Value: string);
var
  P, Start, LB: PChar;
  S: string;
  LineBreakLen: Integer;
begin
  BeginUpdate;
  try
    Clear;
    P := Pointer(Value);
    if P <> nil then
      if CompareStr(LineBreak, sLineBreak) = 0 then
      begin
        // This is a lot faster than using StrPos/AnsiStrPos when
        // LineBreak is the default (#13#10)
        while P^ <> #0 do
        begin
          Start := P;
          while not (P^ in [#0, #10, #13]) do Inc(P);
          SetString(S, Start, P - Start);
          Add(S);
          if P^ = #13 then Inc(P);
          if P^ = #10 then Inc(P);
        end;
      end
      else
      begin
        LineBreakLen := Length(LineBreak);
        while P^ <> #0 do
        begin
          Start := P;
          LB := AnsiStrPos(P, PChar(LineBreak));
          while (P^ <> #0) and (P <> LB) do Inc(P);
          SetString(S, Start, P - Start);
          Add(S);
          if P = LB then
            Inc(P, LineBreakLen);
        end;
      end;
  finally
    EndUpdate;
  end;
end;
Code aus D11.1:
Delphi-Quellcode:
procedure TStrings.SetTextStr(const Value: string);
var
  P, PCurVal, PCurLB, PStartVal, PEndVal, PStartLB, PEndLB: PChar;
  S: string;
  LineBreakLen: Integer;
begin
  BeginUpdate;
  try
    Clear;
    P := Pointer(Value);
    if P = nil then
      Exit;

    LineBreakLen := Length(LineBreak);
    if LineBreakLen = 0 then
    begin
      Add(Value);
      Exit;
    end;

    PEndVal := P + Length(Value);

    // When LineBreak is:
    // * sLineBreak - for compatibility with Windows, Posix and old macOS platforms,
    // we handle #13#10, #10 and #13 as it would be #13#10.
    // * NOT sLineBreak - we use strict checking for LineBreak.
    if CompareStr(LineBreak, sLineBreak) = 0 then
    begin
      while P < PEndVal do
      begin
        PStartVal := P;
        while (P < PEndVal) and not (P^ in [#10, #13]) do Inc(P);
        SetString(S, PStartVal, P - PStartVal);
        Add(S);
        if P^ = #13 then Inc(P);
        if P^ = #10 then Inc(P);
      end;
      Exit;
    end;

    PStartLB := Pointer(LineBreak);
    PEndLB := PStartLB + LineBreakLen;
    PCurLB := PStartLB;
    PStartVal := P;

    while P < PEndVal do
    begin
      while (P < PEndVal) and (P^ <> PStartLB^) do
        Inc(P);
      if P < PEndVal then
      begin
        PCurVal := P + 1;
        Inc(PCurLB);
        while (PCurLB < PEndLB) and (PCurVal < PEndVal) and (PCurVal^ = PCurLB^) do
        begin
          Inc(PCurVal);
          Inc(PCurLB)
        end;
        if PCurLB = PEndLB then
        begin
          SetString(S, PStartVal, P - PStartVal);
          Add(S);
          P := PCurVal;
          PStartVal := P;
        end
        else
          Inc(P);
        PCurLB := PStartLB;
      end;
    end;

    if P > PStartVal then
    begin
      SetString(S, PStartVal, P - PStartVal);
      Add(S);
    end;
  finally
    EndUpdate;
  end;
end;

Geändert von Rolf Frei (25. Aug 2022 um 01:11 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 25. Aug 2022, 07:07
Ein #0 in einem String ist nunmal ein Wert der Probleme produziert.
Filtere ihn davor raus und gut ist.
Du hast eher Glück gehabt das solche fehlerhaften Daten überhaupt so lange kein Probleme verursacht haben und du nicht schon bei anderen Funktionen/Methodenaufrufen an das Problem gestoßen bist das #0 in der C/WinAPI-Welt ein Kennzeichner für eine Stringende ist.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.007 Beiträge
 
Delphi 12 Athens
 
#3

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 25. Aug 2022, 07:08
Mich würde nun interessieren, wieso TString.SetTextStr komplett umgeschrieben wurde und die #0 Zeichen nicht mehr behandelt. Ist das Absicht oder eine Bug?
Das ist offenbar Absicht: https://quality.embarcadero.com/brow...#comment-94090

Insbesondere wird hier wohl das vorige Verhalten als ungewollt betrachtet. Da es nicht dokumentiert ist, kann die Implementierung auch entsprechend angepasst werden. Ich fürchte, du wirst dir deinen eigenen #0-Bereiniger davor schalten müssen. Das würde auch die bisher verborgene Intention klarer machen. Offenbar rechnen die meisten Entwickler nicht damit, dass eine TStringList #0-Zeichen ausfiltert.

Unabhängig davon kenne ich aber auch Fälle, in denen #0-Zeichen in Strings als Separatoren zu weiteren Informationen missbraucht werden, nur um eine korrekte Datenstruktur (z.B. Array, Record) zu vermeiden. Dann wird der erste Part einfach über PChar(S) ausgelesen. Bei den folgenden wird es dann halt komplexer. Sowas kommt meistens durch irgendwelche Quick'n'Dirty Erweiterungen rein und sollte schleunigst refactored werden. Konkret für deinen Fall würde ich eine Art StripZeroChars Funktion empfehlen. Dann ist das Problem ein für alle Mal gebannt.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#4

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 25. Aug 2022, 10:32
Grundsätzlicher Bug?

Warum wird SL.LineBreak beim Einlesen überhaupt "so" verwendet?

Wenn LineBreak irgendwass mit #13 und/oder #10 ist, dann gehören ALLE Arten von Linebreaks richtig behandelt, also egal ob #10, #13#10 oder #13.
Nur wenn LineBreak irgendwas ANDERES ist, dann explizit das zum Tennen suchen.

Ja, man könnte auch auch "Q" oder "," als LineBreak verwenden, aber eigentlich gehört sowas gefälligst ins DelimitedText.




Ob man nun auch #0 als Linebreak interpretiert oder zum kompletten Leseabbruch benutzt, daüber lässt sich streiten.
IMHO hat per se #0 in einem Delphi-Strings keine Bedeutung und sollte somit auch als normaler "Char" behandelt werden.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.007 Beiträge
 
Delphi 12 Athens
 
#5

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 25. Aug 2022, 11:05
IMHO hat per se #0 in einem Delphi-Strings keine Bedeutung und sollte somit auch als normaler "Char" behandelt werden.
Genau das passiert ja nun auch in der TString.SetTextStr . Im Gegensatz zu vorher, wo die #0-Zeichen einfach entfernt wurden. Das alte Verhalten war also streng genommen nicht Delphi-konform, die Änderung also nachvollziehbar.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#6

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 25. Aug 2022, 11:37
Achso ... andersrum verstanden.

Joar, aber ging vorher oft auch nicht anders, da an zuvielen Stellen intern mit PChar gearbeitet wird, was bei #0 aufhört.

(wobei das PChar per se kein Problem ist, aber falsche PChar-Funktionen zu verwenden schon, wo es andere PChar-Funktionen gäbe, welche dennoch mit einem Length-Parameter arbeiten)






Gaaaaanz früher gab es auch mal ein Datei-Ende-Zeichen (85 oder so ... weiß nicht mehr ob Hex oder Dez),
bei welchem TP/Delphi auch gern aufhörte die StringList einzulesen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Rolf Frei

Registriert seit: 19. Jun 2006
629 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 25. Aug 2022, 13:21
Ich habe halt gestern den ganzen Arbeitstag gebraucht herauszufinden was da auf eineam in D11 falsch läuft und ein HTML-Template nun auf einmal nicht mehr richtig verarbeitet wird. Irgendwann habe ich per Zufall entdeckt, dass da an der Stelle wo es aufhört eine #0 drin ist.

Ich bin ja auch eher der Meinung, dass es bisher falsch war und #0 eigentlich nicht entfernt werden sollten. Von daher kann ich mit der Änderung leben. Was mir halt nicht so recht gefällt ist, das ich nun einen Check für #0 machen muss und das eigentlich unnötig Zeit kostet, für einen äusserst seltenen Spezialfall. Der eingentliche Fehler liegt ja hier nicht in Delphi sondern im HTML-Template. Vermutlich lasse ich das auch weg und das Tempalte muss dann halt korrigiert werden.

Geändert von Rolf Frei (25. Aug 2022 um 13:29 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.007 Beiträge
 
Delphi 12 Athens
 
#8

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 25. Aug 2022, 13:48
Der eingentliche Fehler liegt ja hier nicht in Delphi sondern im HTML-Template. Vermutlich lasse ich das auch weg und das Tempalte muss dann halt korrigiert werden.
Es ist in der Regel auch besser die Ursache eines Problems zu beseitigen als nur seine Symptome.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
482 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 12. Sep 2022, 11:13
Was ich mich auch frage ist, wieso man auf die Idee kommt, in den Code einer HTML-Seite Null-Chars einzubauen. Ich wüsste nicht mal jetzt auf Anhieb, ob alle Browser das überhaupt vernünftig darstellen würden/könnten und was dafür die W3-konforme Darstellung wäre. Gerade bei einem Browser, der nun einmal nicht in Pascal, C# oder Java geschrieben wurde.
Dennis
  Mit Zitat antworten Zitat
Rolf Frei

Registriert seit: 19. Jun 2006
629 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: TStringList verhält sich in D11 anders mit enthaltenen #0

  Alt 12. Sep 2022, 13:25
Das macht ja auch keiner mit Absicht, dennoch hat sich hier in einem HTML Template ein NUL Char eingenistet. Woher und wieso wissen wir leider nicht, nur soviel, dass der Code von irgendwoher vom Kunden per Copy/Paste eingefügt wurde. Das Zeichen hat den Browser bisher garnie erreicht, weil das schon vorher durch die Stringlist eliminiert wurde. Neu würde es ankommen, aber auch hier gibt es noch weiterren Code im Webbroker Framework, das dann eben abbricht und den Rest danach nicht mehr liefert. Die Möglichkeit ein NUL mit dem Webbroker FW an den Browser zu senden, war/ist also garnicht möglich.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:58 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz