Название: Как избежать краша в libjpeg при открытии некорректного файла?
Отправлено: Пантер от Декабрь 25, 2012, 13:49
Вот код: C++ (Qt) 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; }
C++ (Qt) 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 происходит падение, как этого избежать? Файл во вложении.
Название: Re: Как избежать краша в libjpeg при открытии некорректного файла?
Отправлено: ecspertiza от Декабрь 25, 2012, 14:24
честно скажу что с libjpeg ни разу не работал, но вот в голову такая мысль пришла, а что если проверять файл на наличие
0xFFD8 и 0xFFD9 - стало быть начало и конец jpg файла ? Хотя может есть более верное решение :-\
Название: Re: Как избежать краша в libjpeg при открытии некорректного файла?
Отправлено: Пантер от Декабрь 25, 2012, 14:27
jpeg_read_header нормально отрабатывает, значит, хидер корректен, по идее.
Название: Re: Как избежать краша в libjpeg при открытии некорректного файла?
Отправлено: xokc от Декабрь 25, 2012, 14:44
А как падения избежать-то хочется? Что бы написало "вы подсунули плохой JPEG" и продолжало ждать нормального JPEG или всё же пыталось бы распаковать хоть что-то из битого JPEG?
Название: Re: Как избежать краша в libjpeg при открытии некорректного файла?
Отправлено: Пантер от Декабрь 25, 2012, 14:46
Первый вариант. То есть, просто должно сказать, что файл не корректен.
Название: Re: Как избежать краша в libjpeg при открытии некорректного файла?
Отправлено: xokc от Декабрь 25, 2012, 16:00
Тогда, видимо, надо почитать документацию на libjpeg в разделе Error handling.
Название: Re: Как избежать краша в libjpeg при открытии некорр
Отправлено: Пантер от Декабрь 26, 2012, 10:58
Решение подсказано на linux.org.ru C++ (Qt) struct JpegError : public jpeg_error_mgr { jmp_buf jmpBuffer; }; static void error_exit (j_common_ptr cinfo) { JpegError *error = static_cast<JpegError *> (cinfo->err); longjmp (error->jmpBuffer, 1); } //------------------------------- bool JpegFormat::load (const QByteArray &data, const QSize &size) { Q_UNUSED (size) jpeg_decompress_struct decompressStruct; JpegError error; decompressStruct.err = jpeg_std_error (&error); error.error_exit = error_exit; #if 0 error.emit_message = emit_message; error.output_message = output_message; error.format_message = format_message; error.reset_error_mgr = reset_error_mgr; #endif //0 if (!setjmp (error.jmpBuffer)) { 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 (); }
|