Перейти к содержимому

Легкий ахтунг внутрях Linux

Захотелось заглянуть внутрь libc Ubuntu Linux 10.04 на реализацию функции bsearch, а там небольшая проблемка:


void *
bsearch (const void *key, const void *base, size_t nmemb, size_t size,
	 int (*compar) (const void *, const void *))
{
  size_t l, u, idx;
  const void *p;
  int comparison;

  l = 0;
  u = nmemb;
  while (l < u)
    {
      idx = (l + u) / 2;
      p = (void *) (((const char *) base) + (idx * size));
      comparison = (*compar) (key, p);
      if (comparison < 0)
	u = idx;
      else if (comparison > 0)
	l = idx + 1;
      else
	return (void *) p;
    }

  return NULL;
}

Проблема в строке


      idx = (l + u) / 2;

При достаточно больших значениях nmemb и поиске ключа из "верхнего" раздела массива, здесь может возникнуть переполнение (если компилятор не отслеживает такие ситуации), и соответственно функция будет зацикливаться.

Конечно, это касается действительно огромных массивов, с более чем 231 элементов для 32-битных систем (где размер size_t равен 4 байтам).

Вариант bsearch во FreeBSD 7.1 не имеет этой проблемы:


void *
bsearch(key, base0, nmemb, size, compar)
	const void *key;
	const void *base0;
	size_t nmemb;
	size_t size;
	int (*compar)(const void *, const void *);
{
	const char *base = base0;
	size_t lim;
	int cmp;
	const void *p;

	for (lim = nmemb; lim != 0; lim >>= 1) {
		p = base + (lim >> 1) * size;
		cmp = (*compar)(key, p);
		if (cmp == 0)
			return ((void *)p);
		if (cmp > 0) {	/* key > p: move right */
			base = (char *)p + size;
			lim--;
		}		/* else move left */
	}
	return (NULL);
}

Легкий ахтунг внутрях Linux: 15 комментариев

  1. Уведомление: Tweets that mention Легкий ахтунг внутрях Linux -- Topsy.com

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *