Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 有什么方法可以访问源代码?_Ruby_Metaprogramming - Fatal编程技术网

Ruby 有什么方法可以访问源代码?

Ruby 有什么方法可以访问源代码?,ruby,metaprogramming,Ruby,Metaprogramming,有几种方法可以从需要/加载库的Ruby代码中访问库的源代码。在这些方法中,有些方法直接读取库文件并对其进行解析。其他人通过一些内置的方法访问源代码,这些方法提供源代码的信息(例如抽象语法树)。在我无法直接读取文件内容的情况下(如前所述),访问源代码的唯一方法是访问提供信息的内置方法。通过重新定义这些方法来做其他事情,我将完全失去对源代码的访问。最小的方法集是什么?如果我将它们重新定义为其他方法,我将完全失去对外部文件上库的源代码的访问权限 重新表述问题 假设: 有一个用户可以在文件a中编写任

有几种方法可以从需要/加载库的Ruby代码中访问库的源代码。在这些方法中,有些方法直接读取库文件并对其进行解析。其他人通过一些内置的方法访问源代码,这些方法提供源代码的信息(例如抽象语法树)。在我无法直接读取文件内容的情况下(如前所述),访问源代码的唯一方法是访问提供信息的内置方法。通过重新定义这些方法来做其他事情,我将完全失去对源代码的访问。最小的方法集是什么?如果我将它们重新定义为其他方法,我将完全失去对外部文件上库的源代码的访问权限


重新表述问题

假设:

  • 有一个用户可以在文件a中编写任何Ruby代码
  • 有一个由我编写的静态Ruby文件B,它加载文件a并调用a中定义的主例程,还定义了一些用户可以在a中使用的类/方法
  • 用户对B没有+r(读)或+w(写)权限
当我运行文件B时,为了让用户无法访问文件B中写入的源代码(通过用户可以在文件A中写入的任何代码),我必须在文件B中重新定义(取消)或删除哪些(标准Ruby)方法

有一些库,如Sporcerer、pry,可以提取它可以访问的方法的源代码。在普通Ruby中必须有一些基本命令,这些库依赖这些命令来访问源代码。是什么方法使这类事情成为可能


如果您不知道完整答案,但知道某个特定库如何提取某个方法的源代码,那么这仍然会有帮助。

如果您使用John Mair(Pry的制造商)的令人敬畏的“method\u source”gem,实际上非常简单: 该方法必须用Ruby(不是C)实现,并且必须从文件(不是irb)加载

下面是一个示例,显示Rails控制台中的方法源代码和方法源代码:

  $ rails console
  > require 'method_source'

  # the following prints out the method code for #lookup in the Rails I18n Backend:

  > I18n::Backend::Simple.instance_method(:lookup).source.display
    def lookup(locale, key, scope = [], options = {})
      init_translations unless initialized?
      keys = I18n.normalize_keys(locale, key, scope, options[:separator])

      keys.inject(translations) do |result, _key|
        _key = _key.to_sym
        return nil unless result.is_a?(Hash) && result.has_key?(_key)
        result = result[_key]
        result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
        result
      end
    end
    => nil 
显示的Ruby代码需要来自已加载的文件, (显然,它必须可读),并且必须是原生Ruby代码(这不适用于编译/链接库)

另见:


    • TL;DR:仅限Ruby的解决方案只能使用
      源位置
      ,因此只需重新定义它以返回类似
      ['/some/empty/file',1]
      的内容即可。C对解释器的攻击不使用
      源位置
      ,但您可以通过阻止/white list
      require
      和friends来防止使用C扩展


      首先,要能够执行Ruby脚本,您必须能够读取它

      但回到问题上来。我知道Sourcify除了在Proc上使用一个小方法和名为
      source\u location
      的方法外,没有使用任何神秘的方法,它给出了定义了方法/Proc时的文件名和行号。我从经验中知道,这种方法非常脆弱,需要编写某种解析器,而且有时只能在合法的情况下工作。因此,如果您在B中重新定义
      源位置
      ,以返回类似
      /dev/null的内容,第0行
      ,并让Sourcify抛出一个非Ruby源异常,那么Sourcify已经退出

      从Pry的角度来看,Pry似乎使用了相同的
      源位置
      方法,所以一箭双雕

      现在,所有这些库都有另一种选择,那就是下拉到C并破解解释器来记录源代码。这几乎是完美的。但我们仍然可以用一种非常简单的方法避免危险。有人可以将Pry方法源代码的所有代码都包含在A中,但如果不需要C库,就不能包含内联C/C扩展。因此,解决方案显而易见:重新定义
      require
      require\u relative
      load
      要么不起作用,要么只允许某些库。这样,你就可以避开C黑客

      在MRI上,除了
      source\u location
      之外,没有其他方法(从Ruby代码中)可以做到这一点。好了

      编辑:根据@banister,从MRI 2.0+中,有一个内置的调用方绑定方法,可以替换源位置。也用核武器


      警告:Ruby不是一种很好的语言。如果你能对它们进行元编程,它们可能会对你进行元编程,除非你处于不同的过程中

      我认为您可以在Java中定义一些抽象类或类似于接口的东西,它们不实现任何东西。接口将从外部组件公开访问。然后,您可以继承抽象类以在内部实现它。在重新定义此类方法时,您可以使用
      模块#alias_方法
      确保您拥有要修改的原始方法的“副本”。必须禁用系统、backtick、fork/exec等。请稍候。你想加载一个“插件”(想不出更好的词),然后通过做一些疯狂的沙箱来阻止它读取应用程序的源代码?在另一个进程中对代码进行沙箱,使用内置的/C级操作系统沙箱功能(我知道Linux有这些功能),并执行一些IPC?s/sourcerer/sorcer?会不会更容易?谢谢。我终于得到了一个中肯的答案。通过取消
      源位置
      ,你认为我也可以避免访问抽象语法树(AST)吗?@sawa你想做的事情非常奇怪——但仅仅搞乱源位置是不够的。调用方的绑定和绑定评估(“文件”)等的组合将返回与源位置大致相同的信息。任何有足够智慧的人都可以使用ge