次の入力データを想定します。
char input[] = {
0x01, 0x02, 0x0a, 0x0b, /* A 32bit integer */
'h', 'e', 'l', 'l', 'o', 0x00,
'w', 'o', 'r', 'l', 'd', 0x00,
0x00 /* Necessary to make the end of the payload. */
};
先頭の 32 整数は次のようになります。
const size_t header_size = sizeof (uint32_t);
入力の解析は、「文字列」の最初の文字を識別し、それへのポインターを格納してから、見つかった文字列の長さ (1+) と同じだけ移動し、入力の最後に到達するまでやり直すことで実行できます。 .
size_t strings_elements = 1; /* Set this to which ever start size you like. */
size_t delta = 1; /* 1 is conservative and slow for larger input,
increase as needed. */
/* Result as array of pointers to "string": */
char ** strings = malloc(strings_elements * sizeof *strings);
{
char * pc = input + header_size;
size_t strings_found = 0;
/* Parse input, if necessary increase result array, and populate its elements: */
while ('\0' != *pc)
{
if (strings_found >= strings_elements)
{
strings_elements += delta;
void * pvtmp = realloc(
strings,
(strings_elements + 1) * sizeof *strings /* Allocate one more to have a
stopper, being set to NULL as a sentinel.*/
);
if (NULL == pvtmp)
{
perror("realloc() failed");
exit(EXIT_FAILURE);
}
strings = pvtmp;
}
strings[strings_found] = pc;
++strings_found;
pc += strlen(pc) + 1;
}
strings[strings_found] = NULL; /* Set a stopper element.
NULL terminate the pointer array. */
}
/* Print result: */
{
char ** ppc = strings;
for(; NULL != *ppc; ++ppc)
{
printf("%zu: '%s'\n", ppc - strings + 1, *ppc)
}
}
/* Clean up: */
free(strings);
分割時にコピーする必要がある場合は、この行を置き換えます
strings[strings_found] = pc;
に
strings[strings_found] = strdup(pc);
free()
使用後およびingの前にクリーンアップ コードを追加しますstrings
。
{
char ** ppc = strings;
for(; NULL != *ppc; ++ppc)
{
free(*ppc);
}
}
上記のコードは、ペイロードの後に少なくとも 1文字'\0'
(NUL
ヌル文字) が続くことを前提としています。
後者の条件が満たされない場合は、他の終了シーケンスを定義/前後に配置するか、他のソースからの入力のサイズを知る必要があります。そうしないと、問題は解決できません。
上記のコードには、次のヘッダーが必要です。
#include <inttypes.h> /* for int32_t */
#include <stdio.h> /* for printf(), perror() */
#include <string.h> /* for strlen() */
#include <stdlib.h> /* for realloc(), free(), exit() */
また、次の定義のいずれかが必要になる場合があります。
#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE
または、Cコンパイラがstrdup()
利用可能にするために他に必要なもの。