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;

.
.
.

より少ないステートメントで同じ効果があると思います。これをもっと質問させてください。プロンプトで定義された保護を使用して、文字列を別の配列にコピーする関数をどのように書くことができますか? また、私が提示した 2 つのプログラムは、私が認識できない方法で何らかの脆弱性を持っていますか?

建設的な意見を歓迎します。

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

ソース内のステートメントが少ないからといって、必ずしも理解しやすいとは限りません。あなたの代替ソリューションの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文字列に no が含まれていると、問題が発生します。これが長さの制限がある理由だと思いますn

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

n配列のサイズよりも大きく、'\0'.

于 2013-09-26T07:04:40.823 に答える
1

これは C では奇妙なことです。

char mol[] = "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 に答える
0

非常によく似たインターフェースはstrncpyです。おそらく、man ページを読むと、エラー モードがより理解できるようになるでしょう。

于 2013-09-26T06:26:37.183 に答える
0

バッファ オーバーフローを防ぐには、常に strncpy を使用することをお勧めします。char * strncpy ( char * destination, const char * source, size_t num ); また、sizeof ではなく strlen を使用することをお勧めします。したがって、ソース文字列が宛先バッファよりも大きい場合でも。宛先バッファをバッファ オーバーフローから保護します。宛先バッファーの最大サイズとして n を使用します。実際、n = strlen(dest_buffer) -1 にします。'\0' に対応します。

于 2013-09-26T06:46:00.007 に答える