integer overflow
От: jyuyjiyuijyu  
Дата: 24.05.11 11:26
Оценка:
Всем привет
при написании класса динамического массива озадачился проверкой на переполнение
решил посмотреть известные реализации взял файл garray.c из библиотеки GLIB
рассмотрим любую функцию оттуда например эту
GArray*
g_array_set_size (GArray *farray,
          guint   length)
{
  GRealArray *array = (GRealArray*) farray;
  if (length > array->len)
    {
      g_array_maybe_expand (array, length - array->len);
      
      if (array->clear)
    g_array_elt_zero (array, array->len, length - array->len);
    }
#ifdef ENABLE_GC_FRIENDLY  
  else if (length < array->len)
    g_array_elt_zero (array, length, array->len - length);
#endif /* ENABLE_GC_FRIENDLY */  
  
  array->len = length;
  
  g_array_zero_terminate (array);
  
  return farray;
}

самое в ней интересное это g_array_maybe_expand открываем смотрим
static gint
g_nearest_pow (gint num)
{
  gint n = 1;

  while (n < num)
    n <<= 1;

  return n;
}

static void
g_array_maybe_expand (GRealArray *array,
              gint        len)
{
  guint want_alloc = g_array_elt_len (array, array->len + len + 
                      array->zero_terminated);

  if (want_alloc > array->alloc)
    {
      want_alloc = g_nearest_pow (want_alloc);
      want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);

      array->data = g_realloc (array->data, want_alloc);

#ifdef ENABLE_GC_FRIENDLY
      memset (array->data + array->alloc, 0, want_alloc - array->alloc);
#endif /* ENABLE_GC_FRIENDLY */

      array->alloc = want_alloc;
    }
}

опять же в ней самое интересное это макрос g_array_elt_len смотрим
#define g_array_elt_len(array,i) ((array)->elt_size * (i))
#define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))

так вот первое переполнение при сложении array->len + len и второе при умножении
elt_size * (i) так вот при использовании GArray можно получать уникальные состояния
например
len = 2147484036
alloc = 1024
тоесть размер занимаемой памяти намного меньше длинны массива абсурд
но при некоторых обстоятельствах запросто подобную фигню получить
вот я пишу сейчас тоже массив и думаю бросить так или проверять на переполнение
если проверять то это тормоза придется к __int64 кастить не хотелось бы этого
оставить так быть неуверенным в правильных результатах всегда
что думаете по этому поводу ?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.