以下代码可能出现什么问题?

时间:2013-04-20 18:56:13

标签: c multithreading buffer buffer-overflow

char* function (char* s)
{
    char buffer[1024];
    strcpy(buffer,s);
    buffer[strlen(s)-1]='\n';
    return buffer;
}

对于这个函数,我认为有三件事可能会使代码失败:

  1. 如果s大于缓冲区,strcpy会失败吗?
  2. 如果s为null,则函数中的第三行将失败?
  3. 在多线程的情况下,此代码会发生什么?它会影响strcpy吗? (函数中的第二行)
  4. 你怎么看? 有更多的事情可能会失败吗?在我的一个假设中我错了吗?

    由于

2 个答案:

答案 0 :(得分:1)

就多线程而言,如果s指向的内存被另一个线程修改或变得无效(例如,如果它被另一个线程释放),则此函数将无法正常工作。

答案 1 :(得分:0)

首先,gcc-4.8 -Wall会向您发出警告:function returns address of local variable

您无法有意义地返回本地数组(或字符串)。至少,声明它static(但这不是多线程友好的)。

然后,strcpy应为if (s) strncpy(buffer, s, sizeof(buffer))以避免缓冲区溢出,并避免取消引用空指针(如果s == NULL)。

你想在换行符之后将字符串终止为零,所以代码类似

size_t slen = s?strlen(s):0;
if (slen>=sizeof(bufber)-1) slen=sizeof(bufber)-2;
memcpy(buf, s, slen);
buffer[slen-1] = '\n';
buffer[slen] = (char)0;

除非buffer是静态的,否则您需要return strdup(buffer);,然后调用方应确保它变为free - d。

真的想要 strdup或者最好asprintf

char* addnewline(const char*s)
{
   char* dynbuf = NULL;
   if (!s) return NULL;
   asprintf(&dynbuf, "%s\n", s);
   return dynbuf;
}

使用重要的约定addnewline调用者应确保结果为free - d

你应该返回堆分配的内存,你应该有一个约定来定义谁将释放它。

您甚至可以使用Boehm's GC,即GC_strdup,而不用担心将结果释放出来。

如果您不想使用asprintf,因为它只是GNU,那么代码

char* addnewline(const char*s) {
  if (!s) return NULL;
  size_t sz = strlen(s);
  char* dynbuf = malloc(sz+2);
  if (!dynbuf) { perror("addnewline malloc"); exit(EXIT_FAILURE); };
  memcpy(dynbuf, s, sz);
  dynbuf[sz] = '\n';
  dynbuf[sz+1] = (char)0;
  return dynbuf;
}

但你确实需要addnewline的结果是堆分配的约定,并且在调用之后应该是free - d。