saw*_*awa 7 ruby metaprogramming
有几种方法可以从需要/加载该库的Ruby代码中访问库的源代码.在这些方法中,有些人直接读取库文件并解析它.其他人通过一些内置方法访问源代码,这些方法提供有关源的信息(例如抽象语法树).在我无法直接读取文件内容的情况下(如前面的方式),访问源的唯一方法是访问提供信息的内置方法.通过重新定义这些方法来做其他事情,我将完全失去对源代码的访问权限.最小的方法集是什么,如果我将它们重新定义为其他方法,我将完全失去对外部文件库的源代码的访问权限?
假设:
我必须重新定义(无效)或通过在文件B中写入来删除(标准Ruby)方法,以使用户无法访问文件B中写入的源(通过用户可以在文件A中编写的任何代码) )当我运行文件B?
有些像sorcerer,pry这样的库可以提取它可以访问的方法的源代码.在纯Ruby中必须有一些原始命令,这些库依赖于这些命令使它们可以访问源代码.有什么方法可以使这种事情成为可能?
如果您不知道完整的答案,但知道某个特定的库如何提取某些方法的来源,那么这仍然会有所帮助.
TL; DR:只有Ruby的解决方案才能使用source_location,所以只需重新定义它就可以返回类似的内容['/some/empty/file', 1].C hacks to the interpreter不使用source_location,但你可以阻止/白名单require和朋友阻止任何C扩展的使用.
首先,要能够执行Ruby脚本,您必须能够读取它...
但回到这个问题.我知道Sourcify除了在Proc和Method上调用一个小方法之外不使用任何神秘的方法source_location,它给出了文件名和行号是一个方法/ proc定义.我从经验中知道这种方法非常脆弱,需要编写某种解析器,有时只能在合法的情况下工作.所以,如果你source_location在B中重新定义以返回类似内容/dev/null, line 0并且让Sourcify抛出一个非Ruby源异常,那么Sourcify已经出局了.
从Pry的来源来看,似乎Pry使用相同的source_location方法,所以两只一石二鸟.
现在,所有这些库都有另一个选项,即下拉到C并破解解释器以记录源代码.这几乎完美无瑕.但我们仍然可以通过一种非常简单的方式避免危险.有人可以在A中包含Pry方法源的所有代码.但是,如果不需要C库,则不能包含内联C/C扩展.因此,解决方案显而易见:重新定义require,require_relative并且load要么不工作,要么只允许某些库.这样,你可以阻止C黑客攻击.
在MRI上,除此之外没有办法(来自Ruby代码)source_location.你去吧!
编辑:根据@banister,来自MRI 2.0+,有binding_of_caller一种内置的方法可以取代源位置.也是这样.;)
警告:Ruby不是一个好的语言.如果你可以对它们进行元编程,除非你处于不同的过程,否则它们可能会对你进行元编程.