Project

General

Profile

Actions

Feature #7525

closed

How to avoid memory leak when something gets wrong and throw exception when using win32api?

Added by mghomn (Justin Peal) over 11 years ago. Updated about 11 years ago.

Status:
Rejected
Target version:
[ruby-core:50616]

Description

require 'win32api'

module Crypto

Common API

NULL = 0
@GetLastError = Win32API.new('kernel32', 'GetLastError', '', 'I')
@lstrlen = Win32API.new('kernel32', 'lstrlenW', 'L', 'I')

Memory API

@RtlMoveMemory = Win32API.new('kernel32', 'RtlMoveMemory', 'PLL', 'I')
@LocalFree = Win32API.new('kernel32', 'LocalFree', 'L', 'I')

Crypto API

CRYPTPROTECT_UI_FORBIDDEN = 0x01
@CryptProtectData = Win32API.new('crypt32', 'CryptProtectData', 'PPPPPLP', 'I')
@CryptUnprotectData = Win32API.new('crypt32', 'CryptUnprotectData', 'PPPPPLP', 'I')

def self.error func
puts "#{func} Error = #{@GetLastError.call()}"
end

def self.encrypt str, entropy, desc
pDataIn = [str.bytesize, str].pack('Lp')
szDataDescr = (desc + "\0").encode(Encoding::UTF_16LE)
pOptionalEntropy = [entropy.bytesize, entropy].pack('Lp')
pvReserved = pPromptStruct = NULL
dwFlags = CRYPTPROTECT_UI_FORBIDDEN
pDataOut = [0, ''].pack('Lp')
return error('CryptProtectData') if @CryptProtectData.call(pDataIn, szDataDescr, pOptionalEntropy, pvReserved, pPromptStruct, dwFlags, pDataOut) == 0
cbData, pbData = pDataOut.unpack('LL')
ret = ' '.encode(Encoding::BINARY) * cbData
return error('RtlMoveMemory') if @RtlMoveMemory.call(ret, pbData, cbData) == 0
return error('LocalFree') if @LocalFree.call(pbData) != NULL
ret
end

def self.decrypt str, entropy, desc
pDataIn = [str.bytesize, str].pack('Lp')
ppszDataDescr = [NULL].pack('L')
pOptionalEntropy = [entropy.bytesize, entropy].pack('Lp')
pvReserved = pPromptStruct = NULL
dwFlags = CRYPTPROTECT_UI_FORBIDDEN
pDataOut = [0, ''].pack('Lp')
return error('CryptUnprotectData') if @CryptUnprotectData.call(pDataIn, ppszDataDescr, pOptionalEntropy, pvReserved, pPromptStruct, dwFlags, pDataOut) == 0
pszDataDescr = ppszDataDescr.unpack('L').first
szDataDescr = ' '.encode(Encoding::UTF_16LE) * @lstrlen.call(pszDataDescr)
return error('RtlMoveMemory') if @RtlMoveMemory.call(szDataDescr, pszDataDescr, szDataDescr.bytesize) == 0
return error('LocalFree') if @LocalFree.call(pszDataDescr) != NULL
szDataDescr.encode!(Encoding::UTF_8)
cbData, pbData = pDataOut.unpack('LL')
ret = ' '.encode(Encoding::BINARY) * cbData
return error('RtlMoveMemory') if @RtlMoveMemory.call(ret, pbData, cbData) == 0
return error('LocalFree') if @LocalFree.call(pbData) != NULL
desc = '' unless desc
return error('Unmatched description') unless desc == szDataDescr
ret.force_encoding(Encoding::UTF_8)
end
end

if $0 == FILE
def test plain, entropy, desc
puts "plain = #{plain}, entropy = #{entropy}, desc = #{desc}"
cipher = Crypto.encrypt(plain, entropy, desc)
puts "cipher = #{cipher.unpack('H*').first}"
recover = Crypto.decrypt(cipher, entropy, desc)
puts "recover = #{recover}"
end

begin
test('abcd', 'efgh', 'ijkl')
rescue
puts $!.to_s.force_encoding(Encoding::UTF_8), $!.backtrace.join($/)
end
end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0