草庐IT

c++ - "printf("%s 行的内存漏洞应该是 %s", argv[1]);"被描述为堆栈溢出?

coder 2023-06-02 原文

今天,我从 Elance.com 参加了一个简短的“C++ 技能测试”。一个问题如下:

What is the security vulnerability of the following line of code:

printf("%s", argv[1]);

Option 1: Format String

Option 2: Stack Overflow <-- This was marked by Elance as the correct answer



在看到问题的最初几秒钟后,用户被提供 10 秒钟来回答这个问题(或自动使问题失败)。 (还有另外两个明显不相关的答案没有被 Elance 标记为正确答案。)

我在找 缓冲区溢出 缓冲区溢出 作为一种选择。

我本能地不喜欢答案堆栈溢出,因为在我的 10 秒内,我在精神上使用了我认为是 standard definition of "Stack Overflow" 的东西。 :

In software, a stack overflow occurs when the stack pointer exceeds the stack bound. The call stack may consist of a limited amount of address space, often determined at the start of the program ...



根据“堆栈溢出”的这个定义,在没有堆栈溢出的情况下,缓冲区溢出是完全可能的 ;仅当程序尝试 时才会发生堆栈溢出。在调用程序的总堆栈分配之外写入 (无论是由于缓冲区溢出,还是由于其他原因是合法的写入,例如为基于堆栈的变量分配内存过多次)。

我 10 秒的直觉告诉我,“缓冲区溢出”是对上面有问题的代码行的更准确描述 - 因为通常(根据我的经验)有足够的空字符( '\0' )通过 RAM 中的垃圾数据填充到在这种情况下,通常会避免实际的堆栈溢出,但实现中的缓冲区溢出似乎是合理的,甚至是可能的。 (但 printf 在这里读取垃圾的可能性可能会假设 argc == 1 ,这样就没有用户提供的 argv[1] ;如果 argv[1] 存在,也许可以假设调用函数可能没有插入NULL 的。问题中没有说明 argv[1] 是否存在。)

因为我想象这里可能存在缓冲区溢出问题,即使没有堆栈溢出,我回答了格式字符串 ,因为只需传递不同的格式字符串,例如 "%.8s" ,这个问题基本上可以避免,所以它似乎是一个更通用的,因此更好的答案。

我的回答被标记为错误。正确答案被标记为“堆栈溢出”。

我现在想到,也许如果有人假设 argv[1]存在,即 只有可能的缓冲区溢出是堆栈溢出,在这种情况下,堆栈溢出实际上可能是正确的答案。但是,即使在这种情况下,将其称为堆栈溢出也不奇怪吗?即使假设 argv[1],缓冲区溢出难道不是描述这个问题的更好方法吗?存在?并且,如果 argv[1]不是 现在,说问题是堆栈溢出而不是更准确的缓冲区溢出是不是很不正确?

我想请教本站专业人士的意见:“堆栈溢出”是否是用上述代码行定义内存安全问题的正确方法?或者,更确切地说,“缓冲区溢出”或“缓冲区溢出”显然是描述问题的更好方法?最后,考虑到为问题的答案(上面)提供的两个选项,答案是模棱两可的,还是“堆栈溢出”(或“格式字符串”)显然是更好的答案?

关于 Elance 测试的切向评论 (与本帖中的问题无关)

Elance 的“ C++ 技能测试”问题均与 有关任何 特定于 C++ 的功能,例如类、模板、STL 中的任何内容或多态性的任何方面。每个问题都是一个彻头彻尾的、直接来自 C 的问题。

因为在Elance所谓的“C++技能测试”中还有很多(至少3个)其他问题是无可争议的错误(比如这个问题:给定 sizeof(int) == sizeof(int*)sizeof(int) == 4 ,那么在代码 int *a, *b; a=b; b++; b-a; 中,什么是b-a ,正确答案列为 4 ,而不是实际正确答案 1 ),并且考虑到测试中没有特定于 C++ 的问题,我已经联系了 Elance 并打算认真对待与组织一起进行有问题的测试。但是,对于本帖中讨论的问题,我不确定问题/答案是否有问题。

最佳答案

这里没有潜在的堆栈溢出。

标准保证argc是非负的,这意味着它可以是 0 .如 argc为正,argv[0]通过 argv[argc-1]是指向字符串的指针。

argc == 0 ,然后 argv[1]不仅仅是一个空指针——它根本不存在。在这种情况下,argv[1]尝试访问不存在的数组元素。 ( argv[1] 等效于 *(argv+1) ;允许添加指针,但取消引用具有未定义的行为。)请注意,在这种情况下,程序名称可以通过 argv[0] 访问。不可用。

argc==1 ,然后 argv[1] == NULL .正在评估 argv[1]是完全有效的,但它产生一个空指针。将空指针传递给 printf"%s"选项具有未定义的行为。我想您可以将其称为格式字符串问题,但真正的问题是在需要指向字符串的非空指针时使用空指针。

argc >= 2 ,然后 argv[1]保证指向一个字符串,printf("%s", argv[1])将简单地打印该字符串的字符,直到但不包括终止 '\0' (保证存在)。

在这种情况下仍然存在潜在的漏洞。报价N1570 7.21.6.1 第 15 段:

The number of characters that can be produced by any single conversion shall be at least 4095.



(N1570 是 C 标准的草案;C++ 指的是 C 标准的部分标准库。)

这意味着实现可能会限制 printf 产生的字符数。称呼。在实践中,可能没有理由强加一个固定的限制; printf可以简单地打印字符,一次一个,直到到达字符串的末尾。但原则上,如果strlen(argv[1]) > 4095 ,如果当前的实现强加了这样的限制,那么行为可能是未定义的。

尽管如此,这并不是我所说的“堆栈溢出”——特别是因为 C++ 标准不使用“堆栈”这个词(除了对“堆栈展开”的几个简短引用)。

大多数这些问题可以通过首先检查来避免:
if (argc >= 2) {
    printf("%s", argv[1]);
}

或者,如果您感到偏执:
if (argc >= 2 && argv[1] != NULL) {
    printf("%s", argv[1]);
}

关于c++ - "printf("%s 行的内存漏洞应该是 %s", argv[1]);"被描述为堆栈溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24232937/

有关c++ - "printf("%s 行的内存漏洞应该是 %s", argv[1]);"被描述为堆栈溢出?的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是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

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从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""-

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  7. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  9. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  10. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

随机推荐