Подробности

[В начало]

Проблема в реализации № S0791

Краткое описание

hsearch_r() падает из-за нарушения внутреннего инварианта

Подробное описание

Изменения в функции hsearch_r() [1], которые были внесены в glibc-2.9, приводят к нарушению внутреннего инварианта и последующему segmentation fault.

Комментарий к функции hsearch_r() в исходном коде glibc гласит:

We use an trick to speed up the lookup. The table is created by hcreate with one more element available. This enables us to use the index zero special. This index will never be used because we store the first hash index in the field used where zero means not used. Every other value means used. The used field can be used as a first fast comparison for equality of the stored and the parameter value. This helps to prevent unnecessary expensive calls of strcmp.

Но в новой версии в поле 'used' хранится значение хеш функции вместо индекса в таблице, а это значение может быть равным нулю. В результате, в случае когда значение хеш функции оказывается равным нулю, то неинициализированные ячейки таблицы (т.е. содержащие 0 в поле 'used') рассматриваются как потенциально содержащие искомое значение, что приводит к разыменованию нулевого указателя при попытке сравнения ключа из этой ячейки с искомым. Пример, приведенный ниже, демонстрирует эту ситуацию.

[1] http://sourceware.org/bugzilla/show_bug.cgi?id=6966

Раздел стандарта

Linux Standard Base Core Specification 3.1, Chapter 13. Base Libraries, 13.3. Interfaces for libc, 13.3.17. Standard Library, 13.3.17.1. Interfaces for Standard Library, Table 13-22. libc - Standard Library Function Interfaces, descriptions of hcreate(), hsearch() and hdestroy() functions.

Пример

#include <stdio.h>
#include <search.h>

int main(void)
{
	char * key[] = { "key2", "gda|yvsp", "" };
	char * data = "data";
	int i;
	
	ENTRY item;
	item.data = data;
	
	hcreate(20);
	
	for(i = 0; i < 3; i++){
		item.key = key[i];
		
		printf("try to insert '%s'='%s'\n", item.key, (char *)item.data);
		hsearch(item, ENTER);
		printf("successful\n");
	}
	
	hdestroy();
	return 0;
}

Компонент

glibc 2.9

Принято

Red Hat Bugzilla, 10100

Статус

Исправлено в glibc-2.10

[В начало]