我刚刚阅读了一个新的 C++ 挑战: http://blogs.msdn.com/b/vcblog/archive/2014/02/04/challenge-vulnerable-code.aspx
提供的代码如果充满问题,有些对任何有良好编程习惯的人来说都是显而易见的,有些只有 C++ 本地人才能看到 :-)
评论中描述了特定行 (37) 特别危险:
ImageFactory::DebugPrintDimensions((ImageFactory::CustomImage*)image);
然后该函数调用 CustomImage 的虚方法(在 CustomImage 中首次定义)。
这据称导致 CustomImage 的第一个成员被视为实例的 vptr(实际上它是一个 unique_ptr)并使它指向的二进制文件被视为可执行文件(可能是恶意的)代码..
虽然我能理解这一点,但我想知道为什么这真的有效。
CustomImage 是一个虚拟类,所以(可能)它的前 4 个字节(假设 X86)是 THE vptr,unique_ptr 成员是下一个。类型转换似乎没有改变任何东西......
...如何执行 unique_ptr 持有的数据?
最佳答案
我的看法(我很高兴得到纠正):
这里,CustomImage 是一个多态类(在 Windows ABI 下有一个 vptr 作为第一个“成员”),但 Image 不是。定义的顺序意味着 ImageFactory 函数知道 CustomImage 是一个 Image,但是 main () 没有。
所以当工厂做的时候:
Image* ImageFactory::LoadFromDisk(const char* imageName)
{
return new (std::nothrow) CustomImage(imageName);
}
CustomImage* 指针被转换为 Image*,一切正常。因为 Image 不是多态的,指针被调整为指向 CustomImage 中的 (POD) Image 实例——但重要的是,这是在 vptr 之后,因为它总是在 MS ABI 的多态类中排在第一位(我假设)。
然而,当我们到达
ImageFactory::DebugPrintDimensions((ImageFactory::CustomImage*)image);
编译器看到从一个它一无所知的类到另一个类的 C 风格转换。它所做的只是获取它拥有的地址并假装它是一个 CustomImage*。该地址实际上指向自定义图像中的 Image;但是因为 Image 是空的,并且大概是空基类优化生效了,所以它最终指向 CustomImage 中的第一个成员,即 unique_ptr.
现在,ImageFactory::DebugPrintDimensions() 假定已将一个指向完全完整的 CustomImage 的指针传递给它,因此地址等于 vptr。但它并没有——它被交给了 unique_ptr 的地址,因为在它被调用的时候,编译器并不知道更多。所以现在它取消引用它认为是 vptr 的东西(我们真正控制的数据),寻找虚函数的偏移量并盲目地执行它——现在我们有麻烦了。
有几件事可以帮助缓解这种情况。首先,由于我们通过基类指针操作派生类,Image 应该有一个虚拟析构函数。这将使 Image 成为多态的,而且很可能我们不会遇到问题(我们也不会泄漏内存)。
其次,因为我们是从基到派生进行转换,所以应该使用 dynamic_cast 而不是 C 风格的转换,后者会涉及运行时检查和正确的指针调整。
最后,如果编译器在编译 main() 时掌握了所有信息,它可能能够警告我们(或正确执行转换,针对 的多态性质进行调整>自定义图片)。因此,也建议将类定义移动到 main() 之上。
关于C++ 转换为 base 和 "overwriting"vptr 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21595943/
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar