DanysysTeam / PS-SFTA

PowerShell Set File Type Association
253 stars 53 forks source link

Convert-Int32 sometimes performs the wrong conversion, due to a Double coming in #17

Closed User1785604260 closed 1 year ago

User1785604260 commented 1 year ago

The $Value parameter on Convert-Int32 will sometimes come in as a Double. When this occurs, the conversion performed will be incorrect and the wrong value is returned.

This is due to an Int32 overflowing into a Double instead of an Int64. The behavior can be seen here:

Write-Host (([int]::MaxValue + 1) -is [double]) (([int]::MaxValue + 1) -is [long])

I think that just adding a [long] type to the $Value parameter will be sufficient to fix this. Wherever the original Int32 overflow arithmetic is occurring could also be fixed to use Int64 arithmetic, but I'm guessing the overflow will never be large enough that the Double to Int64 conversion becomes lossy.

Danyfirex commented 1 year ago

Hello, Could you share a working sample code? maybe some test input and expected output.

Saludos

User1785604260 commented 1 year ago

Hi, try calling Get-Hash with the following value:

Get-Hash ".cs-1-5-21-165441112-333733804-2629664839-1001sfta.notepad++.c01d8dcc908b44a00user choice set via windows user experience {d18b6dd5-6124-4341-9318-804003bafa0b}"

You'll see a Double value 2152293211 come in, which can be observed by adding this inside Convert-Int32:

if ($Value -is [double]) {
    Write-Host $Value -ForegroundColor Red
}

You can see that 2152293211 is too big for an int by executing [int]2152293211, which will give you a convert error.

Now you can see what Convert-Int32 will do by executing:

[System.BitConverter]::ToInt32([System.BitConverter]::GetBytes([double]2152293211))

This will give back the value 1801453568. This is incorrect, the Int64 value 2152293211 downcast to an Int32 should be -2142674085.

You can verify this by doing looking at the binary representation of 2152293211:

[convert]::ToString(2152293211l, 2).PadLeft(64, "0")

Which gives us: 0000000000000000000000000000000010000000010010010110001101011011

If we take the last 32 bits:

[convert]::ToString(2152293211l, 2).PadLeft(64, "0").Substring(32)

Then we get 10000000010010010110001101011011. You can then do:

0b10000000010010010110001101011011

And see that gives -2142674085. This matches what you get from:

[System.BitConverter]::ToInt32([System.BitConverter]::GetBytes([long]2152293211))

To verify as far as an incorrect file association goes, you'll need to call Register-FTA with a real program until you trigger a Double to come into Convert-Int32 like I've done. If you call Register-FTA to swap back and forth between two different programs, you'll see the swap doesn't work correctly when that Double comes in. The hashed value will change once every minute for the same inputs, so keep trying until it triggers.

E.g. do Register-FTA "$env:SystemRoot\notepad.exe" ".txt" followed by Register-FTA "$env:ProgramFiles\Notepad++\notepad++.exe" ".txt" until you trigger this logging I mentioned to add:

if ($Value -is [double]) {
    Write-Host $Value -ForegroundColor Red
}

You'll see that your last Register-FTA call didn't actually work and swap to the new program.