安全な gets

嫌われ者の gets 関数ですが、とりあえずバッファオーバーランだけ防ぐことができれば、それなりに便利に使うことができます。そこで、バッファオーバーランだけ対策し、使い勝手はまったく同じ gets を作ってみました。

#include <stdio.h>
#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 でサイズを指定してください。バッファサイズは起動直後に一度だけ設定し、以後は頻繁に変えない方がよいでしょう。

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/384
このエントリーを含むはてなブックマーク