gpt4 book ai didi

c - 我如何纠正旧 GNU/Linux 机器上的整数溢出行为?

转载 作者:太空宇宙 更新时间:2023-11-03 23:30:14 24 4
gpt4 key购买 nike

我有一些用 C 语言编写的软件,直到现在,它在我测试过的每个系统上都运行良好。我们的一位系统管理员已将它安装在我们的集群上,并且出现了一些奇怪的行为。

在该程序中,我正在使用 Kyoto Cabinet 创建一个 DBM 数据库,但在此框上,该过程在创建数据库之前失败了。该程序采用命令行参数来指定内存映射的大小和 KC 库使用的桶数。它根据 kcdbopen 的文档将这些值附加到文件名。即,如果用户为名为 foo.kch 的数据库文件传递了 --mmap-size=1024 --num-buckets=256,则字符串 foo .kch#msiz=1024#bnum=256 被构建并传递给 kcdbopen

正如我所说,这通常可以正常工作。但是,在这台特定的机器上,该过程将失败并出现无法分配内存的错误。另外,一些调试文本显示它试图创建的文件以一些垃圾字符开头,并且 msiz 和 bnum 数字已经溢出,变得非常大:

Failed to open database �!�u�foo.kch#msiz=249821240256#bnum=4199616: Cannot allocate memory

我正在使用 argp_parse 来解析命令行参数。该代码的相关部分是:

struct arguments
{
char *args[1];
unsigned long int mmap_size;
unsigned long int num_buckets;
};

static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
struct arguments *arguments = state->input;

switch (key)
{
case 'm':
arguments->mmap_size = arg ? atol (arg) : 1024;
break;

case 'b':
arguments->num_buckets = arg ? atol (arg) : 100;
break;

case ARGP_KEY_ARG:
if (state->arg_num >= 1)
argp_usage (state);
arguments->args[state->arg_num] = arg;
break;
...<snip>....

我试图在构建文件名字符串时格外(过度?)谨慎:

void *
zdb_create (char *dbfile, unsigned long int mmap_size, unsigned long int num_buckets,
bool verbose)
{
...<snip>...
char mmap_str[32];
char buckets_str[32];
char db_str[512];
if (strlen (dbfile) > sizeof (db_str) - sizeof (buckets_str) - sizeof (mmap_str))
error (EXIT_FAILURE, errno, "Filename too long");
strncat (db_str, dbfile, strlen (dbfile));
snprintf (mmap_str, sizeof(mmap_str), "#msiz=%lu", mmap_size);
if (strlen (dbfile) + strlen (mmap_str) < sizeof (db_str))
strncat (db_str, mmap_str, 32);
else
error (EXIT_FAILURE, errno, "Filename too long");
snprintf (buckets_str, sizeof(buckets_str), "#bnum=%lu", num_buckets);
if (strlen (dbfile) + strlen (mmap_str) < sizeof (db_str))
strncat (db_str, buckets_str, 32);
else
error (EXIT_FAILURE, errno, "Filename too long");
db = zdb_open (db_str, ZDB_CREATOR, false);
...<snip>...

所以,我刚刚了解到有一个 strtoul 函数,这可能是问题的根源; atol 仅转换为标准的 long 而不是 unsigned long。但是,我想 100% 确定我在去之前解决了问题,并再次打扰系统管理员尝试重新安装(不幸的是,我不可能自己测试它,AFAICT)。这种溢出行为最可能的来源是什么?整数溢出和字符串开头的垃圾字符有关系吗?为什么这在除此之外的大多数系统上都有效?

系统使用的是 Linux 2.6.18,gcc 4.1.2,好吧,很难根据它的 info 页面来判断是哪个版本的 libc...version 2.3.x。我只在更新的系统上测试过,例如 Linux 2.6.32/gcc 4.4.3/libc 2.8 和 Linux 3.9.8/gcc 4.8.1/libc 2.17。

谢谢!

最佳答案

这是有问题的:

  char db_str[512]; // not initialized!
if (strlen (dbfile) > sizeof (db_str) - sizeof (buckets_str) - sizeof (mmap_str))
error (EXIT_FAILURE, errno, "Filename too long");
strncat (db_str, dbfile, strlen (dbfile)); // adding to an uninitialized string!

你想像这样初始化 db_str:

  char db_str[512] = "";

关于c - 我如何纠正旧 GNU/Linux 机器上的整数溢出行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17474951/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com