PascalCoinDev / PascalCoin

P2P cryptocurrency without need of historical operations
MIT License
328 stars 185 forks source link

Using inc(int64, uint64) can lead to compiler crashes and garbage. #127

Closed SkybuckFlying closed 5 years ago

SkybuckFlying commented 6 years ago

On my system this line of code leads to garbage:

      inc(FTotalBalance,block.accounts[iacc].balance);

It's in UAccounts.pas

I am surprised you were able to build PascalCoin at all with Delphi 2010.

The test program below demonstrates that writing code as above is very unreliable and can lead to all kinds of weird problems and bugs.

  1. First of all it can cause a compiler crash/error/abort.

  2. Second of all it can lead to access violations.

  3. Third of all it can lead to garbage in variables.

Advise is to test this for yourself, see the horror in action. If you don't see the horror in action then pls report back cause that would be highly interesting if this only happens on AMD X2 3800+ system.

Perhaps Delphi compiler generates bad code on this system. Would have to install Delphi on other systems to known for sure. So do report back if your findings are inconsistent with the finding below ;)

Further advise is to avoid using "inc". I always found it stupid to complexify code with a function you don't even know wtf it does and is inconsistent in it's behaviour. Now it does turn out it may or may not be the culprit of bugs in Delphi Compiler. My real hunch is that it may be further bugs related to uint64 types, as encountered in the past like UFOs =D

Anyway why use a function which you don't even known the parameters off ?! Quite whacky.

Anyway the bug results in TotalBalance for all accounts to be wrong/garbage !

Inc also relies on {X+} compiler switch/state... so again why complexify code with such a shitty function as inc ? ;)

I don't even known what inc does in X- nor do I care (will care in near future, but not for now ;)), avoid it like plague ;)

{X-} <- more shit to figure out, bye bye for now. REALLY ?! For something as shitty simple as an addition ?!?! LOL

Why programming languages like Delphi and C/C++ have to complexify something as simple as:

X = X + Y; to something as silly as:

Inc( X, Y )

or

X++

or

X += Y;

Fucked up I tell you, Fucked up ! ;) =D HAHAHAHA.

Now these fuckers run risks that their C/C++ compiler contain nasty bugs like this as well ! YIKES ?!

Worth it ?! Hell no, cause you didn't catch it ! ;) =D I DID ! :PPP****

You be lucky ! I was on your """team""".

// Begin of Test Program

program TestProgram;

{$APPTYPE CONSOLE}

{$R *.res}

(*

Test weird inc on int64, uint64 as encountered in PascalCoin.

version 0.01 created on 11 july 2018 !

I always knew uint64 is a bugged type sort of, and also using inc is pretty stupid for something as easy as this.

Funny enough the Delphi XE Seattle compiler completely crashes with the code below !

Pretty fricking unbelievable ! ;) =D

This time it caused an access violation ! Holyshit !

Your results/bugs may vary !

What could be the cause is that inc on 64bit types only works in "extended syntax" is enabled ?!? It said something like that in help file ?! No link to "How to enable extended syntax" ?!?

Gonna document it here just in case, nice way to fuck a code without people knowing about it ;)

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Extended_syntax_(Delphi)

" Extended syntax (Delphi)

Go Up to Delphi Compiler Directives (List) Index

Type: Switch

Syntax: {$X+} or {$X-} {$EXTENDEDSYNTAX ON} or {$EXTENDEDSYNTAX OFF}

Default: {$X+} {$EXTENDEDSYNTAX ON}

Scope: Global

Remarks:

Note: The $X directive is provided for backward compatibility. You should not use the {$X-} mode when writing Delphi applications.

The $X directive enables or disables Delphi's extended syntax:

1 Function statements. In the {$X+} mode, function calls can be used as procedure calls; that is, the result of a function call can be discarded, rather than passed to another function or used in an operation or assignment. Generally, the computations performed by a function are represented through its result, so discarding the result makes little sense. Sometimes, however, a function is called because it performs a task such as setting the value of a global variable, without producing a useful result. 2 The Result variable. In the {$X+} mode, the predefined variable Result can be used within a function body to hold the function's return value. 3 Null-terminated strings. In the {$X+} mode, Delphi strings can be assigned to zero-based character arrays (array[0..X] of Char), which are compatible with PChar types.

This directive also affects the use of the caret (^) to indicate pointers. When {$X+} is in effect (the default), you can omit the caret when referencing pointers. When declaring a pointer, however, the caret is required.

For example:

{$X+} type PMyRec = ^TMyRec; TMyRec = record Data: Integer; end;

var MyRec: PMyRec;

begin New(MyRec); MyRec.Data := 42; {#1} end.

Normally, the line marked #1 would be expressed as:

MyRec^.Data := 42;

But with extended syntax enabled, the caret can be omitted. "

Default it should already be on, so this makes no sense, it seems to be simply some kind of compiler bug.

Bye, Skybuck.

control-alt-c also not working to bring up cpu window... seems like Delphi has gone down hill quite a lot !

Seems delphi compiler is simply bugged and uses wrong address, 00000000000 instead of real variable address, "weird or what ?" ;)

*)

{$X+}

uses SysUtils; // System.SysUtils;

var TotalBalance : int64; SomeBalance : uint64;

procedure Main; begin TotalBalance := 0; SomeBalance := 0; while true do begin // experimenting asm clc; // clear carry flag stc; // set carry flag end;

    // very weird? maybe bug in x86 itself ? Not sure.
    Inc( TotalBalance, SomeBalance );   // I think it might be the "add with carry" that might be overflowing this or something.
                                        // so actually bug may depend on carry flag being set or not !

    // let's try same asm instructions below to see which one actually is causing the failure
    asm
        mov [$00422ec8],$00000000
        mov [$00422ecc],$00000000
        mov [$00422ed0],$00000000
        mov [$00422ed4],$00000000

        // so far so good ^

        // now let's test the ones below:
        mov eax,[$00000000]     // weird what's going on here ? wrong addresses ? seems like it ?!
        mov edx,[$00000004]
        add [$00422ec8],eax
        adc [$00422ecc],edx
    end;

    writeln(TotalBalance);
    sleep(1000);
end;

end;

begin try Main; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; ReadLn; end.

(*

Code generated is:

TestProgram.dpr.105: begin 0041870C 55 push ebp 0041870D 8BEC mov ebp,esp TestProgram.dpr.106: TotalBalance := 0; 0041870F C705C82E420000000000 mov [$00422ec8],$00000000 00418719 C705CC2E420000000000 mov [$00422ecc],$00000000 TestProgram.dpr.107: SomeBalance := 0; 00418723 C705D02E420000000000 mov [$00422ed0],$00000000 0041872D C705D42E420000000000 mov [$00422ed4],$00000000 TestProgram.dpr.110: Inc( TotalBalance, SomeBalance ); 00418737 8B0500000000 mov eax,[$00000000] 0041873D 8B1504000000 mov edx,[$00000004] 00418743 0105C82E4200 add [$00422ec8],eax 00418749 1115CC2E4200 adc [$00422ecc],edx TestProgram.dpr.111: writeln(TotalBalance); 0041874F FF35CC2E4200 push dword ptr [$00422ecc] 00418755 FF35C82E4200 push dword ptr [$00422ec8] 0041875B A18CD54100 mov eax,[$0041d58c] 00418760 E8ABFBFEFF call @Write0Int64 00418765 E856CDFEFF call @WriteLn 0041876A E815BAFEFF call @_IOTest TestProgram.dpr.112: sleep(1000); 0041876F 68E8030000 push $000003e8 00418774 E813F2FFFF call Sleep TestProgram.dpr.108: while true do 00418779 EBBC jmp $00418737 TestProgram.dpr.114: end; 0041877B 5D pop ebp 0041877C C3 ret

*)

// End of Test Program

Bye, Skybuck.

SkybuckFlying commented 6 years ago

!!!

This bug is much more serious then it looked at first sight to me. At first I was under the impression it's just causing TotalBalance for GUI to be calculated wrongly.

Today I set out/forth to fix these nasty bugs. Surprise Surprise, these Inc() functions are used throughout the code, even for calculating such important things as account balances and account fees.

Now that I have attempted to correct these bugs it seems that:

  1. These bugs are exploiteable and could be used to enrich oneselfes.
  2. These bugs are exploiteable and could be used to deprive others of their coins or fees, causing massive fees.
  3. These bugs seem to lead to slightly wrong "fee" calculations, maybe even bigger than I think.
  4. Might also be used to crash clients.

I am just scratching the surface of the implications of these bugs.

One thing became immediately apperent though I am not yet sure:

These changes will require a HARD FORK just to prevent older clients from using wrong calculations.

And this has to happen very first cause somebody may try to EXPLOOOOOIITTTT IT LOLOLOLOLOL.

HHHHHMMMMMMMM who would that be ?! LOL.

Well anybody really, anybody can read this and start messing with the code. (Wow accidently pressed the side buttons of my mouse, you lucky git saved my text, would not have re-typed, another one of those stupid design things... AAARGHH...)

RED ALERT PEOPLE

Your PascalCoin is probably about to be OWNED.

Will be interesting to see what happens ! ;) =D

SkybuckFlying commented 6 years ago

I see original distribution is now 64 bit, will have to investigate to see if bugs are present in 64 bit as well.

Though there could still be 32 bit users out there ! ;)

If the bugs are not present in 64 vs 32 bit this will lead to problems anyway for 32 bit users or 64 bit users since blockchain will be inconsistent and trigger dev warnings.

I suspect the 64 bit mode in Delphi probably does not fix bugs (have not checked yet).

If it were to fix bugs it would detect wrong calculations performed in the past.

The blockchain at least would have to be replaced with a correctly calculated blockchain.

Though I may be jumping to conclusions, but don't think so. Never seen these differences before, so I think they are real... and thus pascalcoin in serious trouble ! ;) investigating...

SkybuckFlying commented 6 years ago

One thing has become apperent:

The "fault tolerant" design of "catching exceptions" and "ignoring exceptions" has now led to a high price:

A wrongly/corrupted blockchain. It may have been better to halt/exit/crash clients instead of letting them continue with wrong calculations and storing them on disk etc.

Currently 32 bit clients will have no idea that their calculations are wrong and will "ignore the exceptions" and continue running, though at least the code steps out and does not continue to run with presumable wrong or different data, not sure which is wrong yet and which is correct, at least it does not proceed with inconsistent data, this is a slight win for pascal coin for now, again these are futher effects to be studied, what is the effect of stepping out of a routine because an exception was raised example:

function TPCSafeBox.AddNew(const blockChain: TOperationBlock): TBlockAccount;

If blockChain.fee<>FTotalFee then Raise Exception.Create(Format('ERROR DEV 20170427-3 blockchain.fee:%d <> Safebox.TotalFee:%d',[blockChain.fee,FTotalFee]));

^ this exception is raised, stepping out of that routine and then happily continueing.

Not sure what effect of this could be.

SkybuckFlying commented 6 years ago

PascalCoin detects errors even in 64 bit then ignores them. Thus something was calculated wrongly.

Time to run test program in 64 bit mode too.

(64 bit original distribution is from 8 may 2018 so it's quite old and cannot contain these fixes yet).

The bug in the test program as originally posted above does not occur in 64 bit mode in Delphi. (Though there may still be other bugs concerning uint64 and so forth, for now it's safe to assume these bugs do not exist until proven)

However by now it's to late to use 64 bit software, the blockchain and maybe safebox seem to have been corrupted with bad calculations, kinda funny that this has gone undetected for now.

This also proves that not checking "account balances" and leaving that bug in there has prevented from detecting this sooner, though it was already detected sooner, so this not a too good situation, kinda funny how "pascal coin" is somewhat fault tolerant... though these bugs could have become quite severe.

What matters now is which software clients are actually running. One idea could be to add some protocol information to show which version of pascalcoin users are using and if it's 32 bit or 64 bit, especially the last part might be missing. This would make users targettable for exploitation though, but it will also show how big the problem might be and for how long it may exist and who to inform to updated.

Will be very interesting to figure out if nanopool runs 32 bit or 64 bit version of pascal coin :)

I suspect probably already 64 bit version and was informed of these problems some while ago ? Then again maybe not... why these bad calculations still showing up ? Blockchain is only 100 blocks so would have been replaced already so I suspect it's inside the safebox itself ? Not sure though...

Could also simply be 32 bit clients performing wrong transaction/fee calculations...

SkybuckFlying commented 6 years ago

On detection of the first wrong calculation the exception is/seems to be catched by:

Try
  Try
    BCExecute;
    FDebugStep := 'Finalized BCExecute';
  Finally
    Terminate;
  End;
Except
  On E:Exception do begin
    TLog.NewLog(lterror,Classname,'Exception inside a Thread at step: '+FDebugStep+' ('+E.ClassName+'): '+E.Message);
    Raise;
  end;
End;

Which causes the "server" to stop/terminate, the PascalCoin GUI will remain open/running though. This stopping of the server probably causes PascalCoin from functioning any further.

So my initial hunch/guess that PascalCoin would keep functioning even with bad calculations was perhaps wrong and pascalcoin simply seizes to operate, a bit of a weird situation, could be a good situation preventing any further nasty things from happening, still weird though, users may be confused too... like what's going on ?!

It's a good thing GUI keeps running though, this allows users to change "log" settings, so they can restart GUI and then inspect logs.

Application Settings should have been stored in TEXT instead of Binary though so that users could have changed it with text editor, though some users may screw this up but that's their problem ;) I would have liked TEXT better. Now the GUI must run to be able to change application settings. Fortunately that's still possible I think, gonna test that too.

(Another interesting question is: what happens to the code in 32 bit mode, where this exception may not trigger, perhaps it simply perform the wrong calculation so it actually matches)

When I write "wrong calculations" I still don't know actually what is going on, still have not even investigated that... getting to that :) Could just be 1 wrong calculation or many, could also been a slight exploit by somebody for now I assume a wrong calculation, a lucky small one perhaps... just off by a couple of 1/10 millis of pascal coin. Could even be a client with "rotting memory chips" causing some bit flips here and there... would be funny if this was a bit flip ! ;)

SkybuckFlying commented 6 years ago

Possible example of the bug in action, logs were on, logs may go fast though, did not spot it at first, now I do spot it, logs were already on:

2018-07-12 10:52:55.255 TID:00000804 [Update] Clear Bank 2018-07-12 10:52:55.257 TID:00000804 [Info] Loading SafeBox with 221700 blocks from file C:\Users\Skybuck\AppData\Roaming\PascalCoin\Data\checkpoint7.safebox 2018-07-12 10:53:07.624 TID:00000804 [Info] Start restoring from disk operations (Max 4294967295) BlockCount: 221700 Orphan: 2018-07-12 10:53:07.728 MAIN:000007F4 [Debug] Block 134614 not found. Cannot read operations 2018-07-12 10:53:08.097 TID:00000804 [Update] New block height:221700 nOnce:1812089910 timestamp:1531142403 Operations:66 Fee:66 SafeBoxBalance:215970500000=215970500000 PoW:0000000000000232D22A4655322697064C5376B95B1E21D171685F42AFEDF784 Operations previous Safe Box hash:52D280671F781CF7D9A6B39002F041126A4236A556F1FC1BC67C933F74E487C9 Future old Safe Box hash for next block:4108B83F1C8D8FEC9E95FA9BFB3223BABEF57C1C27B6988188A99B9385183981

!!! first sign of problems detected by pascal coin start here, the above may also help track this down !!!:

2018-07-12 10:53:08.186 TID:00000804 [Error] Invalid integrity fee! StrongBox:132 Transaction:0 2018-07-12 10:55:32.372 TID:00000804 [Error] Invalid new block 221701: > Block:221701 Timestamp:1531142643 Reward:500000 Fee:0 Target:918742187 PoW:000000000000013C0BFDCBF6BE659EE113D6E4371C01F128DE1EF27A9857C118 Payload:Nanopool/40764809010000000Ù7510000 Nonce:-766378232 OperationsHash:E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855 SBH:4108B83F1C8D8FEC9E95FA9BFB3223BABEF57C1C27B6988188A99B9385183981 2018-07-12 10:55:32.415 TID:00000804 [Error] Exception inside a Thread at step: (Exception): ERROR DEV 20170427-3 blockchain.fee:0 <> Safebox.TotalFee:132

SkybuckFlying commented 6 years ago

With my fixes in place 32 bit mode also detects the same problem:

2018-07-12 11:01:25.733 MAIN:00000628 [Debug] Block 134614 not found. Cannot read operations 2018-07-12 11:01:26.012 TID:0000068C [Update] New block height:221700 nOnce:1812089910 timestamp:1531142403 Operations:66 Fee:66 SafeBoxBalance:215970500000=215970500000 PoW:0000000000000232D22A4655322697064C5376B95B1E21D171685F42AFEDF784 Operations previous Safe Box hash:52D280671F781CF7D9A6B39002F041126A4236A556F1FC1BC67C933F74E487C9 Future old Safe Box hash for next block:4108B83F1C8D8FEC9E95FA9BFB3223BABEF57C1C27B6988188A99B9385183981 2018-07-12 11:01:26.069 TID:0000068C [Error] Invalid integrity fee! StrongBox:132 Transaction:0

For now my assumption is, all my experimenting with pascalcoin did not corrupt my own blockchain and/or safebox and there truely is a problem inside either current blockchain or safebox.

There is a very slight chance that maybe it was stored correctly inside safebox and now that calculations are fixed it shows up, but that chance is very small.

Further conclusions could be:

Most clients including nanopool probably running 32 bit software, the 64 bit sofware should not even be possible to run it would halt ?! Hmmm this is kinda confusing what is it not halting like demonstrated above, where raising exceptions perhaps removed ?!

Will run official pascal distribution next to see what happens.

Very strange result, official pascalcoin distribution starts up just fine... weird or what ? ;)

Will try and compile it then see what happens. (Not tried yet ,one possible conclusion I implemented a fix wrongly or it has a weird side effect now that inc is gone... weird... investigating, though I also replaced some "dec()" functions, LOL... perhaps Dec() is bugged too further complexifieing the situation, AWESOME BUGS ! =D will test and then perhaps replace Dec() too if it appears to be bugged ).

PascalCoin cannot be compiled with Delphi 2010 to 64 bit, so this compile attempt will be aborted.

May try FreePascal/Lazarus instead though.

Conclusion: Would be usefull to mention which compiler was used to create the official distribution to track down compiler bugs ending up in produced executables more easily.

SkybuckFlying commented 6 years ago

Further interesting questions are:

  1. Which compiler was used to produce the 64 bit PascalCoin version ? Delphi 2010 does not have 64 bit compiling as far as I know. Thus some other compiler was used ?

My best guess for now would be FreePascal since the official distribution's GUI seems to blink, which could be a dead give away that this was compiled with FreePascal since these seem Lazarus visual bugs. Lazarus GUI blinks in the same way.

(Could also be an Delphi XE compiler but without the necessary code changes it would not compile, so FreePascal is best guess for now)

If indeed FreePascal was used then this may "complexify" the debugging process even further, many more combinations/scenerios to test.

This may also cause a "rip/rift" in the pascalcoin "community" those using Delphi compilers vs those using FreePascal compilers might end up on different chains/forks of safebox and blockchain. Not yet sure about that, but it is a risk... will be interesting to see if free pascal has the same bugs, probably not though. (It may have other bugs like GUI/visual bugs, hopefully nothing as serious as "addition and subtraction bugs" in crucial functions like the silly inc and dec functions ;)

SkybuckFlying commented 6 years ago

As suspected dec() is affected too. [dcc32 Fatal Error] F2084 Internal Error: URW1175 <- Delphi Seattle compiler error.

Ouch !

SkybuckFlying commented 6 years ago

HAHA, when I replaced dec with my own code I made a mistake and used a + instead of a -. (I was afraid of this checked thought I didn't but I DID, I DID make a little mistake ! HAHA Feel like tweety ! ;) :))

git diff --no-index path1 path2

Catched this ! Thanks GIT !

Checking for more of my own mistakes ! HAHA.

Hopefully this bug not as serious as once believed ! LOL.

Also wrote two special

CatchIncDifference

functions ! =D

SkybuckFlying commented 6 years ago

Ok problem with exception solved.

For now it seems safebox and blockchain was not corrupted ! Few... all calculations ok for now !

Crisis averted ! LOL.

No I don't have to use Free Pascal/Lazarus... thank god ! =D

(The inc code in PascalCoin remains a bit dangerous though at least for 32 bit versions) (Might see if it can be exploited ;))

SkybuckFlying commented 6 years ago

All is not well yet.

I have replaced dec() with CatchDecDifference as well. It's inlined.

What I notice is that the loading of the safebox takes much more time now ?! WHY ?!

  1. First explanation seems somewhat unreasonable. These "debug" functions slow down the code ?!? Ok maybe... it just finished loading. I have other explanations though:
  2. Very maybe exceptions caused the loading to abort here and there, no critical loading functions, but for now I will assume the loading simply takes a bit longer because of slower inc and slower dec...

So far no bugs and no differences detected.

SkybuckFlying commented 6 years ago

What is interesting to notice is that it now finally displays total balance for all accounts properly. I don't think it did that before (when building from sources):

21,642,000 pascal coins in all accounts together.

Official 64 bit pascalcoin distribution does show it properly though.

SkybuckFlying commented 6 years ago

Now that the circle is complete/round, the main question on my mind is:

"How the hell, did I end up in this hell ?!"

Now that the hell is gone and all seems fine, what the hell lead to this situation ?! ;)

The bug with inc and dec is real sort of, the test program proves that, however the bug may be what I am going to call a "phantom" =D

This is a very special kind of bug. It's a bug which doesn't always manifest itself.

I will explain below what this "phantom bug" may be, my working hypothesis is as follows:

  1. Something causes a very weird/stupid corruption bug inside the in-memory-compiler of Delphi IDE.

  2. Which then subsequently leads to faulty code generation for inc/dec or other uint64 related code.

  3. Once the Delphi IDE is restarted, and the project is recompiled from a fresh in-memory-compiler which was somehow not yet corrupted good code generation may happen and good instructions may be emitted.

  4. Until after a while some weird corruption happens inside the in-memory-compiler and from that moment on the bug returns.

Thus it behaves like a "phantom of the opera" a "ghost"... at some point it appears in the in-memory-compiler. Once the IDE is restarted it disappears again, then later on it might re-appear again.

Therefore I believe to catch this Phantom in the act requires inspecting of the "code generation" as it happens. Inspect the "faulty" generated assembler instructions, compared these to a "fresh in-memory-compiler" code generation event and emitted code. There may be a difference, proving that it is a phantom ! =D

Bye for now, Skybuck.

I have some ghost busting to do ! ;) =D

SkybuckFlying commented 6 years ago

I tried to catch the phantom in the act, I was capable of corrupting the compiler with the given example above, however after the compiler corrupted I was unable to produce the results for PascalCoin I first witnessed with the mentioned line way above.

At the time I did not bother to look at the generated assembler instructions. For now I suspect they were faulty (because of compiler corruption) causing the bug/observed problem.

This more or less implies a local problem, however other users of Delphi compilers may find the same results and problems. For now it's safe to assume the official distributions of pascal coin do not contain these bugs. However it may be wise/interesting to inspect previous distributions of pascal coin to see if they contained these bugs, however meanwhile some hard-forks have occured, so those older clients are no longer relevant.

Conclusion could therefore be that PascalCoin is relatively safe from this bug for now, and exploiting it would be very unlikely/shady/doubtfull, however I for one will keep an eye out for these kinds of problems.

My PascalCoin fork (second on the page) has modified code which removes inc/dec from 64 bit parameters/variables just in case.

I hope this will be sufficient to avoid problems in the future, though I fear the worst ;) I expect new compiler problems to occur but for now the situation seems to have been resolved so some degree/level of statisfaction.

Techworker commented 6 years ago

Hi @SkybuckFlying,

we are open to any bug-report, suggestion, whatever, but we are just unable to respond to the issues you create as they are exhausting to follow and to read. We will close all your created issues (even if they are valid) until you are able to describe your problems in a simple way.

And this is a private note: I used to get drunk while developing and this shit can get out of your control really quick, but I luckily got it under control. If this applies to you and you need anyone to talk about that, just get in touch with me and we can work it out. You are unbanned from discord, my nick is @techworker

SkybuckFlying commented 6 years ago

Hi TechWork,

This issue can be solved in two ways:

  1. Either compile PascalCoin with Delphi in 64 bit mode. (Or perhaps use another compiler).
  2. Or find & replace in all units: Inc(A,B) and Dec(A,B) where A is a int64 or uint64 and B is a int64 or uint64 and then replace it with A:=A+B; for Inc and A:=A-B; for Dec.

Once it's replaced the bug will also go away in 32 bit mode. It might cost a little bit of performance though, though it's so little it's more than acceptable.

The bug is field/variable corruption where field/variable is int64 or uint64 where inc/dec processing was used on these fields/variables (because of Delphi XE compiler bug/phantoms)

Bye, Skybuck.

SkybuckFlying commented 6 years ago

From intel manual, maybe this could explain why these inc/dec instructions are working correctly in 64 bit mode:

" 7.3.2.3 Increment and Decrement Instructions in 64-Bit Mode The INC and DEC instructions are supported in 64-bit mode. However, some forms of INC and DEC (the register operand being encoded using register extension field in the MOD R/M byte) are not encodable in 64-bit mode because the opcodes are treated as REX prefixes. "

Seems like Delphi compiler is encoding inc/dec incorrectly in 32 bit mode.