Fri Oct 09 10:29:18 2015: Request 107663 was acted upon. Transaction: Ticket created by am...@marvell.com Queue: Win32-API Subject: Unpacking of byte array still buggy in 0.83_01 Broken in: 0.82, 0.83_01 Severity: Normal Owner: Nobody Requestors: am...@marvell.com Status: new Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=107663 >
Hi, a few ago I stumbled over the error in Win32API::Struct 0.82 when unpacking a BYTE / UNSIGNED CHAR buffer. After some debugging I found that the buffers are being packed using 'a'.$repeat but got unpacked using 'Z'.$repeat. I'm using plain Strawberry Perl 32 and/or 64 bit on Windows 7 64 bit. "This is perl 5, version 22, subversion 0 (v5.22.0) built for MSWin32-x86-multi-thread-64int" I used Win32::API to access FTDI's FTCJTAG.DLL and imported the DLL functions using the corresponding .h file and Win32::API::more. Great so far! Really easy to import a DLL using the .h file contents. The buffers were declared : Win32::API::Struct->typedef ('WriteDataByteBuffer', qw ( BYTE data[64])); Win32::API::Struct->typedef ('ReadDataByteBuffer', qw ( BYTE data[64])); Win32::API::Struct->typedef ('ReadCmdSequenceDataByteBuffer', qw ( BYTE data[128])); Win32::API::Type->typedef('PWriteDataByteBuffer', 'WriteDataByteBuffer*'); Win32::API::Type->typedef('PReadDataByteBuffer', 'ReadDataByteBuffer*'); Win32::API::Type->typedef('PReadCmdSequenceDataByteBuffer', 'ReadCmdSequenceDataByteBuffer*'); The JTAG_Read function in FTCJTAG.DLL in my case/for my device returns 5 bytes. (4 bytes data DWORD and 1 byte JTAG status bits) unpack ('Z64', $buffer->data) stops unpacking at the first 0 found -> WRONG unpack ('a64', $buffer->data) unpacks all bytes even zeros and pads with 0. I fixed it just by changing Z to a. Then while finishing my tasks and documenting, I found the new version 0.83_01 that tries to fix something unpacking arrays. But unpack ('Z'... for any byte sized array is still wrong, and when fixed by a 'a' then the Win32::API::_TruncateToWideNull($$itemvalueref) later on kills the buffer's values. IMHO the Z is only correct if the buffer contains a Zero terminted string, if the buffer contains any binary data, 'a' is the only valid format specifier for the unpack, because 0s (zeros) are preserved. Padding a zero-terminated string with 0s does not harm, whereas cutting binary data at the first zero is harmful. I would suggest $type = $type_size == 1 ? 'Z'.$repeat #have pack truncate to NULL char :'a'.($repeat*$type_size); #manually truncate to wide NULL char later to be changed to $type = 'a'.($repeat*$type_size); Uuuh I can't find Win32::API::_TruncateToWideNull, but commenting out that line (with type='a'....) solves my problem. WideChars should at least be of original size 2... Open for comments, Axel