什么可能导致 CryptStringToBinaryW 崩溃?

tmi*_*hty 2 vb6 winapi

我想将字符串(我通过readAsDataUrl())解码为字节。

首先,我删除data:*/*;base64,然后调用以下命令:

Option Explicit

Private Const CRYPT_STRING_BASE64 As Long = &H1&

Private Declare Function CryptStringToBinaryW Lib "Crypt32.dll" ( _
    ByVal pszString As Long, _
    ByVal cchString As Long, _
    ByVal dwFlags As Long, _
    ByVal pbBinary As Long, _
    ByRef pcbBinary As Long, _
    ByVal pdwSkip As Long, _
    ByVal pdwFlags As Long) As Long

Public Function DecodeBase64(ByVal strData As String) As Byte()
    Dim Buffer() As Byte
    Dim dwBinaryBytes As Long
    dwBinaryBytes = LenB(strData)
    ReDim Buffer(dwBinaryBytes - 1) As Byte

    'within the following call, VB6 crashes:
    If CryptStringToBinaryW(StrPtr(strData), LenB(strData), CRYPT_STRING_BASE64, _
        VarPtr(Buffer(0)), dwBinaryBytes, 0, 0) Then
        ReDim Preserve Buffer(dwBinaryBytes - 1) As Byte
        DecodeBase64 = Buffer
    End If
    Erase Buffer
End Function
Run Code Online (Sandbox Code Playgroud)

现在我称之为:

Dim s$
'code to get base64 string
'code to strip for example "data:image/jpeg;base64,"

Dim nBytes() As Byte
nBytes = DecodeBase64(s) 'Here VB6 crashes
Run Code Online (Sandbox Code Playgroud)

编辑

我现在使用以下替代版本,它可以工作,但我想知道错误是什么:

Public Function DecodeBase64(ByVal sBase64Buf As String) As Byte()
    
    Const CRYPT_STRING_BASE64 As Long = 1
    Const CRYPT_STRING_NOCRLF As Long = &H40000000
    Dim bTmp() As Byte
    Dim lLen As Long
    Dim dwActualUsed As Long
    'Get output buffer length
    If CryptStringToBinary(StrPtr(sBase64Buf), Len(sBase64Buf), CRYPT_STRING_BASE64, StrPtr(vbNullString), lLen, 0&, dwActualUsed) = 0 Then
        'RaiseEvent Error(Err.LastDllError, CSB, Routine)
        GoTo ReleaseHandles
    End If
    'Convert Base64 to binary.
    ReDim bTmp(lLen - 1)
    If CryptStringToBinary(StrPtr(sBase64Buf), Len(sBase64Buf), CRYPT_STRING_BASE64, VarPtr(bTmp(0)), lLen, 0&, dwActualUsed) = 0 Then
        'RaiseEvent Error(Err.LastDllError, CSB, Routine)
        GoTo ReleaseHandles
    Else
        'm_bData = bTmp
    End If
ReleaseHandles:
    DecodeBase64 = bTmp

End Function
Run Code Online (Sandbox Code Playgroud)

编辑

在版本 1 中,dwBinaryBytes这一行是 156080:

dwBinaryBytes = LenB(strData)
Run Code Online (Sandbox Code Playgroud)

在版本 2 中,此行中的 lLen 为 58528:

ReDim bTmp(lLen - 1)
Run Code Online (Sandbox Code Playgroud)

为什么会出现这种差异?为什么作者没有注意到这一点?

小智 7

“CryptStringToBinaryW”需要字符串中的字符数作为参数。这是由“Len”函数返回的。您使用了“LenB”函数,该函数返回字符串中的字节数,该字节数大于字符串中的字符数,因此该函数尝试访问字符串末尾之后的内存,从而导致崩溃。