1

这个函数的目的是将一个字符串复制到一个“缓冲区”——本质上是另一个字符串。然而,这个问题似乎比实际的问题过于复杂。

"Copies at most n-1 characters of string in into the buffer pointed to by
 out. If n is reached, returns -2.  Otherwise, returns -1 for malformed
 input and 0 upon successful completion."

这就是我所拥有的:

#include <stdio.h>
#include <assert.h>

int copyStringN(register char *in, register char *out, register int n){
  //Declarations
    int i; //Dummy index
    if(!in || !out) return -1;
    for(i=0; i<n; i++){
         *out++ = *in++;
    }
    *out = '\0';
    return 0;
}

int main(void){
//Declarations
  char in[] = "I'm not trying to inject malicious code...\\x29A.";
  const int N = sizeof(in);
  char out[N];
  int err;

//Main execution
  printf("\nThis function will copy at most n-1 characters of string into\nthe buffer pointed to by out.\n\n");
  err = copyStringN(in, out, N);
  assert(!err);
  printf("%s\n", out);


  printf("\nPlease press enter to exit...");
  getchar();
  return 0;  
}

建议使用这种一般形式,但它似乎比需要做的事情过于复杂。为什么会n达到?执行应该在之前停止n。此外,不会N = sizeof(in)匹配原始字符串的长度?

就个人而言,我宁愿使用更接近的功能

int copyStringN(register char *in, register char *out)
{
 if((!in || !out) && (sizeof(in)<=sizeof(out))) return -1;
 else{
      while(*t++ = *from++);
      return 0;
 }

}

int main(void){
  //Declarations 
  char in[] = "I'm not trying to inject malicious code...\\x29A.";
  const int N = sizeof(in);
  char out[N];
  int err;

.
.
.

我相信用更少的陈述会产生同样的效果。让我把这个问题变成一个问题,我如何编写一个函数,将字符串复制到另一个数组中,并在提示中定义保护?另外,我介绍的两个程序是否以我不认识的方式存在某种漏洞?

建设性的意见表示赞赏。

4

6 回答 6

1

您建议的替代方案将不起作用。(sizeof(in)<=sizeof(out)将始终是TRUE,因为您正在比较指针(而不是数组),并且它们的大小相同。

如果要制作安全的字符串复制功能,则必须始终传递输出缓冲区长度以进行大小检查,并有办法通知用户输入是否太长而无法输出。

编辑:

由于人们建议使用strncpy,我将提出更安全的替代方案:

int len = snprintf(output, OUTPUT_SIZE, "%s", input);
if(len < 0 || len >= OUTPUT_SIZE) {
    // Failed, handle error
}
于 2013-09-26T06:40:04.303 回答
1

这在 C 中是一件很奇怪的事情。

char mole[] = "mole" 与 char *mole = "mole" 不同

我刚试过:

char *a1 = "mole";
char a2[] = "mole";
printf ("s1: %i s2:%i\n", sizeof(a1), sizeof(a2) );

a1 是一个指针,所以 4 或 8 取决于架构。a2 是一个大小为 5 的数组。

但是您可以将 a2 转换为 char* 而不会发出警告。但是你松了大小。

于 2013-09-26T06:49:00.100 回答
1

您的源代码中较少的陈述并不一定意味着它更容易掌握。您的替代解决方案中的while行可能会起作用,但是根据我的口味,同时做的事情太多了。您首先编写代码供其他人阅读,然后再供编译器阅读。

例如,我喜欢明确地检查NULL和检查。\0

还不清楚您要通过sizeof比较实现什么。除了比较指针的大小(而不是预期的数组?),我认为你的意思是||而不是&&. 如果任一指​​针是NULL它是一个错误,无论大小。

int copyStringN(char *in, char *out)
{
    if((in == NULL) || (out == NULL)) {
        return -1;
    } else {
        while(*in != '\0') {
            *out++ = *in++;
        }
        *out = '\0';
        return 0;
    }
} 

编译后的代码可能不会有太大的不同,在我看来,只有源代码更易于阅读。

然后,如果字符串中恰好没有'\0',那么in您将遇到问题。我想这是有长度限制的原因n

while((*in != '\0') && (n-- > 0)) {
    *out++ = *in++;
}
*out = '\0';

请注意,如果n大于数组的大小并且您错过了'\0'.

于 2013-09-26T07:04:40.823 回答
0

一个非常相似的接口是strncpy。阅读手册页后,错误模式可能会更有意义。

于 2013-09-26T06:26:37.183 回答
0

最好使用 strncpy 来防止缓冲区溢出。char * strncpy ( char * 目标, const char * 源, size_t num ); 此外,最好使用 strlen 而不是 sizeof。因此,即使源字符串大于目标缓冲区。它将保护目标缓冲区免受缓冲区溢出。我会使用 n 作为目标缓冲区的最大大小。实际上使 n = strlen(dest_buffer) -1。容纳'\0'。

于 2013-09-26T06:46:00.007 回答
0

一个基本的 strncpy 看起来像:

char *strncpy(char *d,const char *s,int n){int i=0;while(n--&&d[i++]=*s++);return d;}

但你可以在 n-1 处强制一个空字节

char *sstrncpy(char *d, const char *s, int n){
  int i=0;
  while(--n&&d[i++]=*s++);
  if(!n)d[i]=0;
  return d;
}
于 2013-09-26T07:00:26.420 回答