diff options
author | Michael Leibowitz <michael.leibowitz@intel.com> | 2013-08-15 15:02:54 -0700 |
---|---|---|
committer | Michael Leibowitz <michael.leibowitz@intel.com> | 2013-08-15 15:02:54 -0700 |
commit | 6b0e2a11aeccf2ebc707c22548a0c15c8c2bae06 (patch) | |
tree | d9d59f4b502927634d32832e963db76629ff5a2e /ext/dl/lib | |
parent | 3b35de2a90e26b99e2a6d4f61dc56d6ce7ded748 (diff) | |
download | ruby-upstream.tar.gz ruby-upstream.tar.bz2 ruby-upstream.zip |
Imported Upstream version 1.9.3.p448upstream/1.9.3.p448upstream
Diffstat (limited to 'ext/dl/lib')
-rw-r--r-- | ext/dl/lib/dl/func.rb | 75 | ||||
-rw-r--r-- | ext/dl/lib/dl/import.rb | 8 |
2 files changed, 73 insertions, 10 deletions
diff --git a/ext/dl/lib/dl/func.rb b/ext/dl/lib/dl/func.rb index 3c2245f..9a984ed 100644 --- a/ext/dl/lib/dl/func.rb +++ b/ext/dl/lib/dl/func.rb @@ -11,13 +11,50 @@ module DL include DL include ValueUtil + if DL.fiddle? + # :stopdoc: + CALL_TYPE_TO_ABI = Hash.new { |h, k| + raise RuntimeError, "unsupported call type: #{k}" + }.merge({ :stdcall => + (Fiddle::Function::STDCALL rescue Fiddle::Function::DEFAULT), + :cdecl => Fiddle::Function::DEFAULT, + nil => Fiddle::Function::DEFAULT + }).freeze + private_constant :CALL_TYPE_TO_ABI + # :startdoc: + + def self.call_type_to_abi(call_type) # :nodoc: + CALL_TYPE_TO_ABI[call_type] + end + private_class_method :call_type_to_abi + + class FiddleClosureCFunc < Fiddle::Closure # :nodoc: all + def initialize ctype, arg, abi, name + @name = name + super(ctype, arg, abi) + end + def name + @name + end + def ptr + to_i + end + end + private_constant :FiddleClosureCFunc + + def self.class_fiddle_closure_cfunc # :nodoc: + FiddleClosureCFunc + end + private_class_method :class_fiddle_closure_cfunc + end + def initialize cfunc, argtypes, abi = nil, &block if DL.fiddle? - abi ||= Fiddle::Function::DEFAULT + abi ||= CALL_TYPE_TO_ABI[(cfunc.calltype rescue nil)] if block_given? - @cfunc = Class.new(Fiddle::Closure) { + @cfunc = Class.new(FiddleClosureCFunc) { define_method(:call, block) - }.new(cfunc.ctype, argtypes) + }.new(cfunc.ctype, argtypes, abi, cfunc.name) else @cfunc = cfunc end @@ -55,6 +92,9 @@ module DL super else funcs = [] + if $SAFE >= 1 && args.any? { |x| x.tainted? } + raise SecurityError, "tainted parameter not allowed" + end _args = wrap_args(args, @stack.types, funcs, &block) r = @cfunc.call(@stack.pack(_args)) funcs.each{|f| f.unbind_at_call()} @@ -76,16 +116,18 @@ module DL def bind(&block) if DL.fiddle? - @cfunc = Class.new(Fiddle::Closure) { - def initialize ctype, args, block - super(ctype, args) + @cfunc = Class.new(FiddleClosureCFunc) { + def initialize ctype, args, abi, name, block + super(ctype, args, abi, name) @block = block end def call *args @block.call(*args) end - }.new(@cfunc.ctype, @args, block) + }.new(@cfunc.ctype, @args, abi, name, block) + @ptr = @cfunc + return nil else if( !block ) raise(RuntimeError, "block must be given.") @@ -118,6 +160,25 @@ module DL end def unbind() + if DL.fiddle? then + if @cfunc.kind_of?(Fiddle::Closure) and @cfunc.ptr != 0 then + call_type = case abi + when CALL_TYPE_TO_ABI[nil] + nil + when CALL_TYPE_TO_ABI[:stdcall] + :stdcall + else + raise(RuntimeError, "unsupported abi: #{abi}") + end + @cfunc = CFunc.new(0, @cfunc.ctype, name, call_type) + return 0 + elsif @cfunc.ptr != 0 then + @cfunc.ptr = 0 + return 0 + else + return nil + end + end if( @cfunc.ptr != 0 ) case @cfunc.calltype when :cdecl diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb index eec65cd..a4fa406 100644 --- a/ext/dl/lib/dl/import.rb +++ b/ext/dl/lib/dl/import.rb @@ -231,11 +231,13 @@ module DL def bind_function(name, ctype, argtype, call_type = nil, &block) if DL.fiddle? - closure = Class.new(Fiddle::Closure) { + klass = Function.instance_eval { class_fiddle_closure_cfunc } + abi = Function.instance_eval { call_type_to_abi(call_type) } + closure = Class.new(klass) { define_method(:call, block) - }.new(ctype, argtype) + }.new(ctype, argtype, abi, name) - Function.new(closure, argtype) + Function.new(closure, argtype, abi) else f = Function.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype) f.bind(&block) |