LINUX.ORG.RU

Как избежать краша в libjpeg при открытии некорректного файла?

 ,


0

2

Вот файл

Вот код:

static void error_exit (j_common_ptr cinfo)
{
	Q_UNUSED (cinfo)
	qDebug() << Q_FUNC_INFO;
}

static void output_message (j_common_ptr cinfo)
{
	Q_UNUSED (cinfo)
	qDebug() << Q_FUNC_INFO;
}

static void emit_message (j_common_ptr cinfo, int msg_level)
{
	Q_UNUSED (cinfo)
	Q_UNUSED (msg_level)
	qDebug() << Q_FUNC_INFO;
}

static void format_message (j_common_ptr cinfo, char *buffer)
{
	Q_UNUSED (cinfo)
	Q_UNUSED (buffer)
	qDebug() << Q_FUNC_INFO;
}

static void reset_error_mgr (j_common_ptr cinfo)
{
	qDebug() << Q_FUNC_INFO;
	cinfo->err->num_warnings = 0;
	cinfo->err->msg_code = 0;
}
bool JpegFormat::load (const QByteArray &data, const QSize &size)
{
	Q_UNUSED (size)
	qDebug() << Q_FUNC_INFO;

	jpeg_decompress_struct decompressStruct;
	jpeg_error_mgr error;

	decompressStruct.err = jpeg_std_error (&error);
	jpeg_CreateDecompress (&decompressStruct,
			        JPEG_LIB_VERSION,
				sizeof (decompressStruct));
	error.error_exit = error_exit;
	error.emit_message = emit_message;
	error.output_message = output_message;
	error.format_message = format_message;
	error.reset_error_mgr = reset_error_mgr;

	auto inBuf = reinterpret_cast<const unsigned char *> (data.constData());
	jpeg_mem_src (&decompressStruct,
			const_cast<unsigned char *> (inBuf),
			data.size());

	if (jpeg_read_header (&decompressStruct, true) != JPEG_HEADER_OK) {
		jpeg_destroy_decompress (&decompressStruct);
		return false;
	}

	decompressStruct.out_color_space = JCS_GRAYSCALE;
	jpeg_start_decompress (&decompressStruct);

	size_ = QSize (decompressStruct.image_width, decompressStruct.image_height);
	data_.fill (0,
				decompressStruct.image_width * decompressStruct.image_height
			   );
	auto outBuf = reinterpret_cast<unsigned char *> (data_.data());

	while (decompressStruct.output_scanline < decompressStruct.image_height) {
		jpeg_read_scanlines (&decompressStruct, &outBuf, 1);
		outBuf += decompressStruct.image_width;
	}

	jpeg_finish_decompress (&decompressStruct);
	jpeg_destroy_decompress (&decompressStruct);

	return true;
}

В jpeg_start_decompress происходит падение, как этого избежать?

★★★★

Последнее исправление: panter_dsd (всего исправлений: 1)

Так, глупый вопрос... А это последняя версия libjpeg?
Мне пока не приходит ничего в голову, кроме как исправить баг в libjpeg и использовать свою версию.

UVV ★★★★★
()

Вот валгринд.

void error_exit(j_common_ptr) 
==17255== Invalid read of size 8
==17255==    at 0x64F4C99: start_input_pass (in /usr/lib64/libjpeg.so.8.0.2)
==17255==    by 0x64F8ADB: jinit_master_decompress (in /usr/lib64/libjpeg.so.8.0.2)
==17255==    by 0x64EF974: jpeg_start_decompress (in /usr/lib64/libjpeg.so.8.0.2)
==17255==    by 0x4E48F9A: Core::Image::JpegFormat::load(QByteArray const&, QSize const&) (jpegformat.cpp:89)
panter_dsd ★★★★
() автор топика

В jpeg_start_decompress происходит падение, как этого избежать?

Починить jpeg_start_decompress(). Ваш КО. Если сам не можешь, то тебе в Job.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от panter_dsd

Они слинкованы с тем же libjpeg? Ты уверен, что до него дело доходит? Посмотри исходники, или хотя бы ltrace.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от panter_dsd

Пересобери пакет с отладочной инфой и получишь больше информации о сути проблемы.

UVV ★★★★★
()
Ответ на: комментарий от panter_dsd

turbo намекает на то, что это неофициальная версия с патчами от студента Васи Пупкина, поэтому работать она может как угодно

Reset ★★★★★
()

man libjpeg

error_exit (j_common_ptr cinfo)

Receives control for a fatal error. [...] Control must NOT return to the caller; [...]

Deleted
()

Открыл своим вьювером этот файл - не крешнулся, тупо не смог его декодировать. Использую media-libs/libjpeg-turbo. Но, думаю, и с media-libs/jpeg проблем бы не возникло.

andreyu ★★★★★
()
Ответ на: комментарий от Reset

turbo намекает на то, что это неофициальная версия с патчами от студента Васи Пупкина, поэтому работать она может как угодно

Использую ее, работает очень шустро. Не падает на файле ТСа.

andreyu ★★★★★
()
Ответ на: комментарий от Deleted

Как избежать падения — вернуть управление из error_exit() в JpegFormat::load() через longjmp.

все верно, для этого обычно заводят структуру вроде:

struct 
{
	jpeg_error_mgr	pub;
	jmp_buf		jmp_buffer;
}

чтоб в error_exit скастовать cinfo->err, получить jmp_buffer и вернуться в пользовательскую функцию

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

Спасибо. Сделал так

struct my_error_mgr : public jpeg_error_mgr {
	jmp_buf setjmp_buffer;
};

static void error_exit (j_common_ptr cinfo)
{
	my_error_mgr *myerr = (my_error_mgr *) cinfo->err;
	longjmp (myerr->setjmp_buffer, 1);
}

bool JpegFormat::load (const QByteArray &data, const QSize &size)
		{
			Q_UNUSED (size)
			qDebug() << Q_FUNC_INFO;

			jpeg_decompress_struct decompressStruct;
			my_error_mgr error;

			decompressStruct.err = jpeg_std_error (&error);

			error.error_exit = error_exit;
			error.emit_message = emit_message;
			error.output_message = output_message;
			error.format_message = format_message;
			error.reset_error_mgr = reset_error_mgr;

			if (!setjmp (error.setjmp_buffer)) {
				jpeg_CreateDecompress (&decompressStruct,
									   JPEG_LIB_VERSION,
									   sizeof (decompressStruct)
									  );

				auto inBuf = reinterpret_cast<const unsigned char *> (data.constData());
				jpeg_mem_src (&decompressStruct,
							  const_cast<unsigned char *> (inBuf),
							  data.size());

				if (jpeg_read_header (&decompressStruct, true) != JPEG_HEADER_OK) {
					jpeg_destroy_decompress (&decompressStruct);
					return false;
				}

				decompressStruct.out_color_space = JCS_GRAYSCALE;
				jpeg_start_decompress (&decompressStruct);

				size_ = QSize (decompressStruct.image_width, decompressStruct.image_height);
				data_.fill (0,
							decompressStruct.image_width * decompressStruct.image_height
						   );
				auto outBuf = reinterpret_cast<unsigned char *> (data_.data());

				while (decompressStruct.output_scanline < decompressStruct.image_height) {
					jpeg_read_scanlines (&decompressStruct, &outBuf, 1);
					outBuf += decompressStruct.image_width;
				}

				jpeg_finish_decompress (&decompressStruct);
				jpeg_destroy_decompress (&decompressStruct);
			}


			return !data_.isEmpty ();
		}
panter_dsd ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.