简体   繁体   English

在C中复制此提示符所定义的字符串的安全实用方法是什么?

[英]What would be a safe and practical way to copy a string as defined by this prompt in C?

The purpose of this function is to copy a string into a "buffer" - essentially another string. 此函数的目的是将字符串复制到“缓冲区” - 本质上是另一个字符串。 However, the problem seems overly complicated than what would be practical. 然而,问题似乎过于复杂而不实际。

"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."

This is what I have: 这就是我所拥有的:

#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;  
}

This general form was suggested, but it seems overly convoluted than what needs to be done. 提出了这种一般形式,但它似乎比需要做的事情过于复杂。 Why would n ever be reached? 为什么会n曾经达到? The execution should stop before n . 执行应该在n之前停止。 Furthermore, wouldn't N = sizeof(in) match the length of the original string? 此外, N = sizeof(in)不会匹配原始字符串的长度吗?

Personally, I would rather use a function closer to 就个人而言,我宁愿使用更接近的功能

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;

.
.
.

I believe it would have the same effect with less statements. 我相信它会用较少的陈述产生同样的效果。 Let me make this more of a question, how could I write a function that copies a string into another array with the protection defined in the prompt? 让我更多地提出一个问题,我怎么能写一个函数将一个字符串复制到另一个数组中并在提示符中定义了保护? Also, are the two programs that I presented somehow vulnerable in a way I don't recognize? 另外,我提出的两个程序是否以某种我不认识的方式易受攻击?

Constructive input is appreciated. 建设性的意见表示赞赏。

Your suggested alternative will not work. 您建议的替代方案无效。 (sizeof(in)<=sizeof(out) will always be TRUE , because you are comparing pointers (and not arrays), and they are the same size. (sizeof(in)<=sizeof(out)将始终为TRUE ,因为您正在比较指针(而不是数组),并且它们的大小相同。

If you want to make safe string copy function, you must always pass output buffer length for size checking, and have means to inform user if input was too long for output. 如果要创建安全字符串复制功能,则必须始终传递输出缓冲区长度以进行大小检查,并且必须通知用户输入是否太长而无法输出。

Edit: 编辑:

Since people have suggested to use strncpy , I will present safer alternative: 由于人们建议使用strncpy ,我将提出更安全的替代方案:

int len = snprintf(output, OUTPUT_SIZE, "%s", input);
if(len < 0 || len >= OUTPUT_SIZE) {
    // Failed, handle error
}

This is a strange thing in C. 这在C中是一件奇怪的事情。

char mole[] = "mole" is not the same as char *mole = "mole" char mole [] =“mole”与char * mole =“mole”不同

I just tried: 我刚尝试过:

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

a1 is a pointer, so 4 or 8 depending on the architecture. a1是一个指针,所以4或8取决于架构。 a2 is an array of size 5. a2是一个大小为5的数组。

But you can convert a2 to a char* without warnings. 但是您可以在没有警告的情况下将a2转换为char *。 But you loose the size. 但你放大了。

Fewer statements in your source does not necessarily imply that it is simpler to grasp. 您的来源中较少的陈述并不一定意味着它更容易掌握。 The while row in your alternative solution may work, but is doing too many things at the same time for my taste. 替代解决方案中的while行可能有效,但根据我的口味同时做了太多事情。 You are writing code first for other human beings to read, then for a compiler to read. 首先编写代码供其他人阅读, 然后供编译器阅读。

I like for example making the NULL and \\0 checking explicit. 我喜欢例如使NULL\\0检查显式。

It is also unclear what you are trying to achieve with the sizeof comparison. 目前还不清楚你正在努力实现与什么sizeof比较。 Besides comparing size of pointers (instead of intended arrays?), I think you meant || 除了比较指针的大小(而不是预期的数组?),我认为你的意思是|| instead of && . 而不是&& If either pointer is NULL it is an error, whatever the size. 如果任一指​​针为NULL ,则无论大小如何都是错误。

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

The compiled code is probably not going to be much different, only the source is more human readable in my opinion. 编译后的代码可能不会有太大的不同,在我看来,只有源代码更具人性化。

Then if there happens to be no '\\0' in the in string you are going to have problems. 然后,如果in字符串中没有'\\0' ,您将遇到问题。 I suppose this is the reason for having a length limit n . 我想这是长度限制n的原因。

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

Note that you would still be in trouble if n is greater than the size of your arrays and you miss a '\\0' . 请注意,如果n大于数组的大小并且错过了'\\0'则仍然会遇到麻烦。

A very similar interface is strncpy . 一个非常相似的界面是strncpy Perhaps the error modes will make more sense after you read the man page. 阅读手册页后,错误模式可能更有意义。

It is always better to use strncpy to prevent buffer overflow. 使用strncpy来防止缓冲区溢出总是更好。 char * strncpy ( char * destination, const char * source, size_t num ); char * strncpy(char * destination,const char * source,size_t num); Also, better to use strlen rather than sizeof. 另外,最好使用strlen而不是sizeof。 So, Even if the source string is greater than the destination buffer. 因此,即使源字符串大于目标缓冲区。 It will protect the destination buffer from buffer overflow. 它将保护目标缓冲区免受缓冲区溢出。 I would use n as the maximum size of the destination buffer. 我会使用n作为目标缓冲区的最大大小。 And In fact make n = strlen(dest_buffer) -1. 事实上,使n = strlen(dest_buffer)-1。 To accommodate '\\0'. 容纳'\\ 0'。

a basic strncpy would look like: 一个基本的strncpy看起来像:

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

but you could force a null byte at n-1 但你可以在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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM