草庐IT

c++ - 中毒某些 API 函数(不是维护者)

coder 2023-11-13 原文

相关例如: How to poison an identifier in VC++?
What does it mean to "poison a function" in C++?

有没有办法“正确地”毒化一些声明(或实现)不受我控制的函数?

具体来说,我试图防止意外使用某些可能导致意外结果的 Windows API 函数,例如CreateFileA(使用 T 宏隐藏了您混合使用 ANSI 和 Unicode 的事实)或 SetWindowLong(这将导致您的程序无声地失败,没有错误,也没有有机会知道在 64 位系统上出了什么问题)。

我对“正确”投毒的定义是,尝试调用函数会破坏构建并出现可读错误(如果错误发生在源代码中的正确位置,则加分)。
最好,这应该是可移植的,并且至少它必须与 GCC 和 clang 一起工作。

到目前为止我尝试过/看过的内容:

预处理器

最简单、最直接的解决方案是利用预处理器:

#define CreateFileA __poison_ANSI_CreateFileA

这对于一个特定的功能以及其他几个功能都非常有效,完全按预期工作,并有一个精确的错误提示问题并指向源代码中的正确位置:

error: no matching function for call to '__poison_ANSI_CreateFileA'
note: expanded from macro 'CreateFile'
note: expanded from ... (precise location in source)

对于不同的功能,需要为每个功能起一个唯一的名称,以避免定义冲突的错误,这很繁琐但很容易做到。到目前为止一切顺利,除了它不适用于 MinGW-w64 header 本身使用可变参数宏篡改名称的函数,例如 CreateWindowSetWindowLong。无论如何,无论是否中毒,这些编译都很好。

语用

#pragma GCC poison,clang 恰好也能理解(并且还具有自己的版本),看起来和听起来应该完全按照我的意愿行事,并且以尽可能地道的方式. las,它不起作用。或者更确切地说,它太好了
当中毒名称出现在声明中时,使用 pragma 指令中毒的函数已经触发错误,这意味着......每次,在每个包含 header 的构建中。这对写程序不是很有帮助!

属性

这些有一个巨大的缺点,即您必须准确地复制类型定义,以免一方面在合法调用中出现“模糊函数调用”错误。另一方面,它们不起作用。 clang 提示 __attribute__((__error__)) 但忽略 gnu::__error__gnu::error 以及 gnu::已弃用。此外,标准的 [[deprecated]] 一切都很好,但似乎什么也没做(编译很好,甚至没有警告?!)。

有什么我可以做的吗?

最佳答案

已找到一种通过在命名空间中添加同一函数的另一个声明来加强歧义的方法。没有使用 pragmas 或 attrbiutes,应该可以移植到任何 C++11 编译器:

#include <stdio.h>

#define POISONED_BY_NAME(name) \
    namespace Poisoned \
    { \
        using function_type = decltype(::name); \
        extern function_type* name; \
    } \
    using namespace Poisoned;


POISONED_BY_NAME(puts)

int main()
{
    puts("Hello"); 
}

Visual Studio 消息:

error C2872: 'puts': ambiguous symbol
1>c:\program files\windows kits\10\include\10.0.17763.0\ucrt\stdio.h(353): note: could be 'int puts(const char *)'
1>c:\test.cpp(43): note: or       'Poisoned::function_type (__cdecl *__cdecl Poisoned::puts)'

海湾合作委员会消息:

main.cpp: In function 'int main()':
main.cpp:16:5: error: reference to 'puts' is ambiguous
     puts("Hello");
     ^~~~
main.cpp:12:22: note: candidates are: 'int (* Poisoned::puts)(const char*)'
     POISONED_BY_NAME(puts)
                      ^~~~
main.cpp:7:35: note: in definition of macro 'POISONED_BY_NAME'
             extern function_type* name; \
                                   ^~~~
In file included from main.cpp:1:
/usr/include/stdio.h:695:12: note:                 'int puts(const char*)'
 extern int puts (const char *__s);
            ^~~~

关于c++ - 中毒某些 API 函数(不是维护者),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41858089/

有关c++ - 中毒某些 API 函数(不是维护者)的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

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

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

  3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  4. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  5. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  6. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  7. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  8. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  9. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  10. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

随机推荐