![]() |
Wert eines Defines merken und wiederherstellen
Hallo,
ein Nutzer der DEC (Delphi Encryption Compendium) hat einen Bug gemeldet, der zu einem Integer Overflow führen kann. Details siehe hier: ![]() Mit dem dort skizzierten Testprogramm und einer > 600 MB Datei bekomme ich das in D12.0 nachvollzogen und finde, dass es in TDECHash.Increment8 in DECHashBase.pas in der Unterprozedur AddC hier knallt:
Delphi-Quellcode:
Ok, packe ich das Value := Value + Add; in {$Q-} {$Q+} ein knallt es nicht mehr und auch alle
procedure AddC(var Value: UInt32; const Add: UInt32; var Carry: Boolean);
begin if Carry then begin Value := Value + 1; Carry := (Value = 0); // we might cause another overflow by adding the carry bit end else Carry := False; Value := Value + Add; Carry := Carry or (Value < Add); // set Carry Flag on overflow or keep it if already set end; bisher funktionierenden unit Tests funktionieren weiter. Nur: ich will ja nicht einfach $Q+ danach anmachen, egal ob es schon an war oder nicht. Ich hab' mir jetzt das hier überlegt:
Delphi-Quellcode:
Spricht da was dagegen?
{$IFDEF Q+}
{$define USES_OVERFLOW_CHECKING} {$ENDIF} {$Q-} Value := Value + Add; {$IFDEF USES_OVERFLOW_CHECKING} {$Q+} {$undefine USES_OVERFLOW_CHECKING} {$ENDIF} Carry := Carry or (Value < Add); // set Carry Flag on overflow or keep it if already set Grüße TurboMagic |
AW: Wert eines Defines merken und wiederherstellen
Es gibt seit Jahren schon den Wunsch einer PUSH-Funktion, also vorher Zustand speichern und nachher wiederherstellen, aber neeeeeeeeeee :cry:
Vor allem, da diese Prüfung nur mit Einbuchstabigen Options funktioniert. Nja, innerhalb eigener Units setze ich sowas zu Beginn der Unit und ein zurücksetzen ist (meistens) unnötig, ansonsten mach ich das UNDEF auch zu Beginn ... immer alles in sich Konsistent, ohne dass man auf Vorhergehendes/Nachfolgendes achten muß.
Delphi-Quellcode:
{$UNDEF USES_OVERFLOW_CHECKING} // oder mit Else (vor allem beim Einzeiligen)
{$IFOPT Q+} {$DEFINE USES_OVERFLOW_CHECKING} {$ENDIF} {$Q-} Value := Value + Add; {$IFDEF USES_OVERFLOW_CHECKING} {$Q+} {$ENDIF}
Delphi-Quellcode:
//{$UNDEF USES_OVERFLOW_CHECKING} {$IFOPT Q+} {$DEFINE USES_OVERFLOW_CHECKING} {$ENDIF}
{$IFOPT Q+} {$DEFINE USES_OVERFLOW_CHECKING} {$ELSE} {$UNDEF USES_OVERFLOW_CHECKING} {$ENDIF} {$Q-} Value := Value + Add; {$IFDEF USES_OVERFLOW_CHECKING} {$Q+} {$ENDIF} |
AW: Wert eines Defines merken und wiederherstellen
Danke! Habe deine untere Variante mit leicht geänderter Formatierung jetzt übernommen.
Splittet man das in mehrere Zeilen zeigt einem die IDE nun schön welche der beiden Varianten aktiv ist ;-) |
AW: Wert eines Defines merken und wiederherstellen
Ohhh, och muß zugeben, dass ich beim neuen ausgegrauten Highlighting noch garnicht nachgesehn hab, wie es jetzt aussieht. :oops:
|
AW: Wert eines Defines merken und wiederherstellen
Das funktioniert nur, wenn das auszugrauende in einer separaten Zeile steht!
Darum hab' ich deine Lösung leicht umformatiert. |
AW: Wert eines Defines merken und wiederherstellen
und ich dachte Emba hätte es richtig eingebaut :stupid:
|
AW: Wert eines Defines merken und wiederherstellen
Hi,
There is few tricks can be used, but i can't find valuable for you in this case without affecting the performance for this performance critical procedure. This is perfect workaround for 32bit but will not compile for 64 for the obvious reason
Code:
Its assembly
procedure AddC(var Value: UInt32; Add: UInt32; var Carry: Boolean);
begin Value := Value + Add; PByte(Value) := PByte(Value) + Ord(Add); end;
Code:
The overhead is one instruction in this case.
Project5.dpr.15: Value := Value + Add;
0041A2BC 0110 add [eax],edx 0041A2BE 7305 jnb $0041a2c5 0041A2C0 E83FB3FEFF call @IntOver Project5.dpr.16: PByte(Value) := PByte(Value) + Ord(Add); 0041A2C5 0110 add [eax],edx Project5.dpr.21: end; 0041A2C7 C3 ret but all the other tricks and shenanigans that work for both platforms i can think of will introduce huge overhead instead of one or two instruction. Like this one
Code:
Generated code :
procedure AddC(var Value: UInt32; Add: UInt32; var Carry: Boolean);
begin Value := Value + Add; Value := UInt32(PByte(Value) + Ord(Add)); end;
Code:
Project5.dpr.15: Value := Value + Add;
0041A2BC 0110 add [eax],edx 0041A2BE 7305 jnb $0041a2c5 0041A2C0 E83FB3FEFF call @IntOver Project5.dpr.16: Value := UInt32(PByte(Value) + Ord(Add)); 0041A2C5 8B08 mov ecx,[eax] 0041A2C7 03CA add ecx,edx 0041A2C9 8908 mov [eax],ecx Project5.dpr.22: end; 0041A2CB C3 ret
Code:
We have stupid and outdated compiler !
Project5.dpr.15: Value := Value + Add;
00000000004261E8 0111 add [rcx],edx 00000000004261EA 7305 jnb AddC + $11 00000000004261EC E8AF12FEFF call @IntOver Project5.dpr.16: Value := UInt32(PByte(Value) + Ord(Add)); 00000000004261F1 8B01 mov eax,[rcx] 00000000004261F3 8BD2 mov edx,edx 00000000004261F5 488D0410 lea rax,[rax+rdx] 00000000004261F9 8901 mov [rcx],eax Project5.dpr.22: end; 00000000004261FB 488D6520 lea rsp,[rbp+$20] 00000000004261FF 5D pop rbp 0000000000426200 C3 ret Though the above result is on XE8, and i have no idea on how or will it even compile on newer versions. |
AW: Wert eines Defines merken und wiederherstellen
Tja, seit Kurzem sind in neuen Projekten standardmäßig die Bereichs- und Überlaufprüfungen aktiv.
Wer dass nicht Will, braucht es einfach nur zu deaktivieren. (In den Projektoptionen, oder nur an dieser Stelle im Code) Klar, es produziert zwar mehr Code, aber ich finde es schon sinnvoller. (nur die standardmäßig aktiven Debug-DCUs sind und bleiben IMHO einfach nur nötigender Schwachsinn) Aber bei der Pointer-Mathematik scheint diese Prüfung nicht eingebaut zu sein. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz