小编LuC*_*LuC的帖子

不安全的指针和 Clang

也许只是我度过了奇怪的一天,但我有一些关于Clang警告的问题,需要一个简短的例子。

假设有一段时间有这样一段代码

/// \file  unsafe.c
#include  <stddef.h>

static int  goo (int * pi, size_t a)
{
    return pi[a];
}

int  main (int argc, char *argv[])
{
    (void)argc;
    (void)argv;
    int     goz[4] = { 0, };
    
    return goo(goz, 0);
}
Run Code Online (Sandbox Code Playgroud)

然后你按照如下方式使用 Clang

 # clang --version
clang version 16.0.3
Target: i686-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files (x86)\LLVM\bin

 # clang -std=c11 -Weverything unsafe.c -o unsafe.exe
unsafe.c:4:24: warning: 'pi' is an unsafe pointer used for buffer access
      [-Wunsafe-buffer-usage]
static int  goo (int …
Run Code Online (Sandbox Code Playgroud)

c clang

8
推荐指数
1
解决办法
934
查看次数

缺少 memset_s (C11) 的重要原因

我确信编码中存在很多缓冲区溢出风险,其中许多风险是通过标准库的“_s”安全函数解决的。尽管如此,我发现自己有时对其中一些感到困惑。

假设我有一些这样的片段

uint8_t a[5];
...
size_t  z = 6;
...
memset(a, 0, z);  // Overflow!
Run Code Online (Sandbox Code Playgroud)

一些编译器(C11)可能建议更好地使用memset_s; 因为我是一个糟糕的程序员,所以我刚刚将我的代码更新为这个全新的东西,我的方式:

uint8_t  a[5];
...
rsize_t  max_array = 56;  // Slipped finger, head in the clouds, etc.
rsize_t  z = 6;
...
memset_s(a, max_array, 0, z);  // So what?
Run Code Online (Sandbox Code Playgroud)

如果我只是将错误添加到另一个参数,那会memset_s更好吗?memset

增加的安全性在哪里,如果添加一个新参数只是添加一个可能会出错的新参数。我本可以在第一个修订版中更正我的代码,并且仍然可以合法地调用缓冲区上定义良好的操作。

抛开带有未经检查的零指针的情况,怎么会memset糟糕呢memset_s

[编辑]

经过一番努力,我还发现了导致我的设置中出现警告的设置。这可能对某人有帮助。

该警告来自 Clang-tidy,在 Visual Studio 扩展“Clang power tools”中调用。在其默认设置中,它启用了 Clang-tidy检查器security.insecureAPI.DeprecatedOrUnsafeBufferHandling ”,它模仿默认的 …

c c11

7
推荐指数
1
解决办法
455
查看次数

strtok_s 和编译器 C11 向前兼容

C11 中的声明strtok_s及其用法看起来与 Visual Studio 2022 (17.4.4) 和 GCC 12.2.0 捆绑的最新编译器(查看 MinGW64 发行版)中的in 编译器非常不同。strtok_s

我担心这种不同的形式早在 C11 之前就已被开发为更安全且被接受的替代品strtok。如果有人想要使用strtok_s并保持 C11 合规,现在会发生什么?

编译器提供的库是否兼容 C11?

也许只是我被一些显而易见的事情愚弄了,有人可以帮助我......


这是 C11(与 C17 和 C23 的早期草案类似):

char *strtok_s(char * restrict s1,
    rsize_t * restrict s1max,
    const char * restrict s2,
    char ** restrict ptr);
Run Code Online (Sandbox Code Playgroud)

同样可以在safec 库中找到一个很好的参考

MSC/VC和 GCC 的形式为

char* strtok_s(
    char* str,
    const char* delimiters,
    char** context
);
Run Code Online (Sandbox Code Playgroud)

c gcc msvcrt visual-studio mingw-w64

4
推荐指数
1
解决办法
192
查看次数

将 __attribute__((used)) 设置为 C 变量/常量没有效果

在 ARM GCC(纯 C 代码)上,当我声明一个常量时,如下所示

__attribute__((used,section(".rodata.$AppID")))
const uint8_t   ApplicationID[16] = {
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x12, 0x34, 0x00, 0x00
};
Run Code Online (Sandbox Code Playgroud)

没有在代码中引用它,它已被优化,并在地图文件上的废弃输入部分中列出。仅当我在源代码的其他地方引用它时,它才会包含在二进制输出中。

仅仅“ used”标签就足够了吗?在GCC手册(6.34.1公共变量属性)中我读到:

用过的

此属性附加到具有静态存储的变量,意味着即使看起来该变量未被引用,也必须发出该变量。

意思是把它放在指定段的固定内存地址,供单独的应用程序检查它

我正在运行 NXP MCUXpresso 11.1 提供的 ARM GCC,报告详细版本为

GNU C17 (GNU Tools for Arm Embedded Processors 8-2019-q3-update) version 8.3.1 20190703 (release) [gcc-8-branch revision 273027] (arm-none-eabi)
compiled by GNU C version 5.3.1 20160211, GMP version 6.1.0, MPFR version 3.1.4, …
Run Code Online (Sandbox Code Playgroud)

c gcc arm nxp-microcontroller

3
推荐指数
1
解决办法
5768
查看次数

标签 统计

c ×4

gcc ×2

arm ×1

c11 ×1

clang ×1

mingw-w64 ×1

msvcrt ×1

nxp-microcontroller ×1

visual-studio ×1