请考虑以下示例:
unsigned short c = // ...
if (c > 0xfffful)
c = 0xfffful;
Run Code Online (Sandbox Code Playgroud)
因为unsigned short实际上可能大于16位,我想将snprintf十六进制格式之前的值限制为固定大小的缓冲区.
然而,海湾合作委员会(但没有铿锵)发出警告:comparison is always false due to limited range of data type [-Wtype-limits].
这是海湾合作委员会的一个错误还是我错过了什么?据我所知,我的机器unsigned short上只有16位,但在其他平台上并不能保证这一点.
请考虑以下代码:
struct S {
enum class EnumClass {
one
} ;
enum Enum {
one
};
};
int main()
{
S s;
S::EnumClass e = s.EnumClass::one; // <- Doesn't compile with clang
S::Enum e11 = s.Enum::one;
S::Enum e12 = s.one;
}
Run Code Online (Sandbox Code Playgroud)
一切都适用于GCC,但clang(3.8和3.9都没有)编译s.EnumClass::one,给出错误:'S::EnumClass::one' is not a member of class 'S'.
鉴于未编码的枚举工作正常,这似乎是一个错误.
我正在编写一个使用 Tesseract 进行字符识别的 GUI 应用程序。/bin/sh -c我想允许用户指定在文本准备好时执行的自定义 shell 命令。问题是识别的文本实际上可以包含任何内容,例如&& rm -rf some_dir。
我的第一个想法是让它像许多其他程序一样,用户可以在文本条目中键入命令,然后printf()命令中的特殊字符串(例如 in )被适当的数据替换(在我的例子中,可能是%t)。然后整个字符串被传递到execvp(). 例如,这是 qBittorrent 的屏幕截图:

问题是,即使我在替换之前正确转义文本%t,也没有什么可以阻止用户在说明符周围添加额外的引号:
echo '%t' >> history.txt
Run Code Online (Sandbox Code Playgroud)
所以要执行的完整命令是:
echo ''&& rm -rf some_dir'' >> history.txt
Run Code Online (Sandbox Code Playgroud)
显然,这是一个坏主意。
第二个选项只让用户选择一个可执行文件(带有文件选择对话框),因此我可以手动将 Tesseract 中的文本argv[1]放入execvp(). 这个想法是,可执行文件可以是一个脚本,用户可以在其中放置他们想要的任何内容并使用"$1". 这样,命令注入是不可能的(我认为)。以下是用户可以创建的示例脚本:
#!/bin/sh
echo "$1" >> history.txt
Run Code Online (Sandbox Code Playgroud)
这种方法有什么陷阱吗?或者也许有更好的方法来安全地将任意文本作为参数传递给 shell 脚本中的程序?