安全な gets
嫌われ者の gets 関数ですが、とりあえずバッファオーバーランだけ防ぐことができれば、それなりに便利に使うことができます。そこで、バッファオーバーランだけ対策し、使い勝手はまったく同じ gets を作ってみました。
#include <string.h>
#include <assert.h>
static size_t limit = 256;
size_t set_gets_limit(size_t n)
{
size_t result = limit;
limit = n;
return result;
}
char *gets(char *s)
{
size_t i, n = limit - 1;
int c = 0;
assert(s != NULL);
for (i = 0; i < n; i++)
{
c = getchar();
if (c == EOF) /* エラーまたはファイル終端 */
{
if (ferror(stdin))
{
s = NULL;
}
break;
}
else if (c == 'n')
{
break;
}
s[i] = (char)c;
}
s[i] = '\0';
if (c != 'n') /* 行の途中で切れた場合... */
{
do
{
c = getchar();
} while (c != 'n' && c != EOF);
}
return s;
}
マルチスレッド環境では、getchar を使うのではなく、flockfile で排他制御を行いつつ getchar_unlocked で読み込むなどの対応が必要になります。
使い方ですが、デフォルトでは gets に渡すバッファのサイズは 256 バイトであると仮定しています。バッファを確保するには、256 バイト以上のサイズを持たせてください。バッファサイズを変更するには set_gets_limit でサイズを指定してください。バッファサイズは起動直後に一度だけ設定し、以後は頻繁に変えない方がよいでしょう。

