Win10 又帶著Bug來了!部分 FLAC 格式音樂檔案損壞,已釋出緊急更新修復

Editor發表於2021-06-02

他來了,他來了,他又帶著bug走來了!


5月底,微軟釋出的一份最新文件,稱修復了一個令眾多使用者苦惱的問題。Win10 檔案管理器中存在一個 Bug,可使部分 FLAC 格式音訊檔案損壞。(好傢伙,無損變全損,這我可受不住)


微軟稱,在 Win10 2004 及以上版本中,如果使用檔案管理器修改 FLAC 音訊檔案的後設資料,比如標題、藝術家或者其他音訊後設資料,將使 FLAC 檔案損壞,無法播放。


部分 FLAC 檔案開頭會包含 ID3 幀頭,其中包含歌手、標題、專輯名稱、年代、風格等資訊。


Win10 又帶著Bug來了!部分 FLAC 格式音樂檔案損壞,已釋出緊急更新修復



而在 Win10 2004 及以上版本中,檔案資源管理器會忽略 ID3 幀頭,因為它預設判定 FLAC 檔案使用 4 位元組 fLaC 開頭。因此當使用者使用檔案資源管理器修改 FLAC 檔案的後設資料時,就會把 ID3 幀頭覆蓋掉,從而破壞原有的 FLAC 檔案結構,使音樂播放器無法正常識別。


該bug影響多個Windows 10版本(Home、Pro、Enterprise、Education、Pro Education和Pro for工作站)和版本2004和版本20H2。


微軟已針對該 Bug 釋出了緊急修復更新,在 KB5003214 更新中,微軟確認已修復該問題,大家安裝即可。


除了KB 5003214更新,微軟還提供了一個PowerShell指令碼,可用於修復以前損壞的FLAC音樂檔案。


要修復FLAC檔案,請按照以下步驟操作:


1. 開啟notepad,並輸入下方內容


    # Copyright 2021 Microsoft
    # This script will repair a FLAC file that has been corrupted by Media Foundation in reference to KB5003430.
    # Refer to KB5003430 for further information
    param(
    [parameter(Mandatory=$true,
    HelpMessage="The path to the FLAC file that has been corrupted by Media Foundation",
    ValueFromRemainingArguments=$true)]
    [ValidateScript({ -not [String]::IsNullOrEmpty($_) -and (Test-Path $_) })]
    [String]$File
    )
    # We need to back up the current file incase we have any errors
    $FileDirectory = Split-Path -Resolve $File
    $Filename = Split-Path -Leaf -Resolve $File
    $FullPath = Join-Path -Resolve $FileDirectory $Filename
    $Filename = [String]::Format("Backup_{0:yyyyMMdd_hhmmss}_{1}", [DateTime]::Now, $Filename)
    $BackupLocation = Join-Path $FileDirectory $Filename
    Write-Output "Microsoft FLAC Repair Tool. This tool will repair a FLAC audio file that was corrupted when editing its details."
    Write-Output "Affected File: $FullPath"
    Write-Output "A backup of the file will be made: $BackupLocation"
    Write-Output "Do you wish to continue?"
    $choice=$host.ui.PromptForChoice("Fixing FLAC Script", "Do you wish to continue", ('&Yes', '&No'), 1)
    function ParseStreamInfoMetadataBlock([System.IO.FileStream]$stream)
    {
    $blockType = $stream.ReadByte()
    $lastBlock = ($blockType -shr 7) -ne 0
    $blockType = $blockType -band 0x7F
    if ($blockType -ne 0)
    {
    return $false
    }
    $blockSize = (($stream.ReadByte() -shl 16) -bor ($stream.ReadByte() -shl 8) -bor $stream.ReadByte())
    if ($blockSize -lt 34)
    {
    return $false
    }
    $minAudioBlockSize = ($stream.ReadByte() -shl 8) -bor $stream.ReadByte()
    $maxAudioBlockSize = ($stream.ReadByte() -shl 8) -bor $stream.ReadByte()
    if ($minAudioBlockSize -lt 16 -or $maxAudioBlockSize -lt 16)
    {
    return $false
    }
    $minFrameSize = (($stream.ReadByte() -shl 16) -bor ($stream.ReadByte() -shl 8) -bor $stream.ReadByte())
    $maxFrameSize = (($stream.ReadByte() -shl 16) -bor ($stream.ReadByte() -shl 8) -bor $stream.ReadByte())
    $sampleInfo = (($stream.ReadByte() -shl 24) -bor ($stream.ReadByte() -shl 16) -bor ($stream.ReadByte() -shl 8) -bor $stream.ReadByte())
    $sampleRate = $sampleInfo -shr 12
    $channelCount = (($sampleInfo -shr 9) -band 0x7) + 1
    $bitsPerSample = (($sampleInfo -shr 4) -band 0x1F) + 1
    [UInt64]$sampleCount = (($stream.ReadByte() -shl 24) -bor ($stream.ReadByte() -shl 16) -bor ($stream.ReadByte() -shl 8) -bor $stream.ReadByte())
    $sampleCount = (([UInt64]$sampleInfo -band 0xF) -shl 32) -bor $sampleCount
    $MD5HashBytes = New-Object byte[] 16
    $stream.Read($MD5HashBytes, 0, $MD5HashBytes.Length)
    $MD5Hash = [Guid]($MD5HashBytes)
    if ($sampleRate -eq 0)
    {
    return $false
    }
    # Passing these checks means that we likely have a stream info header and can rebuild the file
    Write-Output "File Stream Information"
    Write-Output "Sample Rate: $sampleRate"
    Write-Output "Audio Channels: $channelCount"
    Write-Output "Sample Depth: $bitsPerSample"
    Write-Output "MD5 Audio Sample Hash: $MD5Hash"
    return $true
    }
    if ($choice -eq 0)
    {
    Copy-Item $FullPath -Destination $BackupLocation -Force
    $stream = [System.IO.File]::Open($FullPath, [System.IO.FileMode]::Open)
    $stream.Seek(4, [System.IO.SeekOrigin]::Begin)
    while ($stream.ReadByte() -eq 0) {}
    # We now need to figure out where a valid FLAC metadata frame begins
    # We are likely pointing to the last byte of the size member so we'll seek back 4 bytes and retry
    $flacDataStartPosition = $stream.Position - 4
    $stream.Seek($flacDataStartPosition, [System.IO.SeekOrigin]::Begin)
    while (-not(ParseStreamInfoMetadataBlock($stream)))
    {
    $flacDataStartPosition = $flacDataStartPosition + 1
    $stream.Seek($flacDataStartPosition, [System.IO.SeekOrigin]::Begin)
    }
    # Insert the start code
    $stream.Seek($flacDataStartPosition, [System.IO.SeekOrigin]::Begin)
    if (Test-Path "$FullPath.tmp")
    {
    Remove-Item "$FullPath.tmp"
    }
    $fixedStream = [System.IO.File]::Open("$FullPath.tmp", [System.IO.FileMode]::CreateNew)
    [byte[]]$startCode = [char[]]('f', 'L', 'a', 'C');
    $fixedStream.Write($startCode, 0, $startCode.Length)
    $stream.CopyTo($fixedStream)
    $stream.Close()
    $fixedStream.Close()
    Move-Item -Force "$FullPath.tmp" $FullPath
    }



    2. 點選儲存,將檔案儲存為 FixFlacFiles.ps1,儲存型別設定為(*.txt)

    3. 在Windows資源管理器中找到儲存的PowerShell指令碼,然後單擊「使用PowerShell執行」



    4. 在彈出的對話方塊中,輸入不可播放的fLAC檔案的檔名,然後點選「enter」



    Win10 又帶著Bug來了!部分 FLAC 格式音樂檔案損壞,已釋出緊急更新修復



    Win10 又帶著Bug來了!部分 FLAC 格式音樂檔案損壞,已釋出緊急更新修復

    公眾號ID:ikanxue

    官方微博:看雪安全

    商務合作:wsc@kanxue.com



    相關文章