2013-05-28 2 views
1

Я использую библиотеку zdelta (http://cis.poly.edu/zdelta/), чтобы сжать кучу двоичных файлов и столкнулась с проблемой, когда декомпрессия почти всегда segfaults, даже с интерфейсом командной строки. Просто интересно, если кто-то столкнулся с этим раньше?
Я сделал некоторую изоляцию ошибок: результат сжатия с моим кодом такой же, как и у меня с CLI (команда ./zdc reference.bin fileToCompress.bin > compressedFile.bin.del), поэтому я предполагаю, что компрессия работает нормально. Сбивая с толку часть, я использую A.bin в качестве справки и сжимаю против себя, тогда все работает отлично. Как только я попробую другой файл, он segfaults (сжатие B.bin с A.bin является ссылкой, например). То же самое с декомпрессионным CLI.

код для сжатия, bufferIn является несжатыми данными и bufferOut представляет собой область буфера вывода, который является достаточно большим (в десять раз входного буфера, так что даже если сжатие растет файловых вещи должны еще работать):библиотека сжатия zdelta segfaults

int rv = zd_compress(reference, refSize, 
        bufferIn, inputSize, 
        bufferOut, &outputSize); 

документация для компресса:

433 /* computes zdelta difference between target data and reference data 
434 * 
435 * INPUT: 
436 * ref  pointer to reference data set 
437 * rsize size of reference data set 
438 * tar  pointer to targeted data set 
439 * tsize size of targeted data set 
440 * delta pointer to delta buffer 
441 *  the delta buffer IS allocated by the user 
442 * *dsize size of delta buffer 
443 * 
444 * 
445 * OUTPUT parameters: 
446 * delta pointer to zdelta difference 
447 * *dsize size of zdelta difference 
448 * 
449 * zd_compress returns ZD_OK on success, 
450 * ZD_MEM_ERROR if there was not enough memory, 
451 * ZD_BUF_ERROR if there was not enough room in the output 
452 * buffer. 
453 */ 
454 ZEXTERN int ZEXPORT zd_compress OF ((const Bytef *ref, uLong rsize, 
455      const Bytef *tar, uLong tsize, 
456      Bytef *delta, uLongf* dsize)); 

==============================

треска е для декомпрессии, bufferIn является сжатыми данными и bufferOut представляет собой область буфера вывода, который в 1000 раз, чем входная (плохая практика да, но я хотел бы выяснить Segfault первым ..):

int rv = zd_uncompress(reference, refSize, 
         bufferOut, &outputSize, 
         bufferIn, inputSize); 

Документация для unpresspress:

518 /* rebuilds target data from reference data and zdelta difference 
519 * 
520 * INPUT: 
521 * ref  pointer to reference data set 
522 * rsize size of reference data set 
523 * tar  pointer to target buffer 
524 *   this buffer IS allocated by the user 
525 * tsize size of target buffer 
526 * delta pointer to zdelta difference 
527 * dsize size of zdelta difference 
528 * 
529 * 
530 * OUTPUT parameters: 
531 * tar  pointer to recomputed target data 
532 * *tsize size of recomputed target data 
533 * 
534 * zd_uncompress returns ZD_OK on success, 
535 * ZD_MEM_ERROR if there was not enough memory, 
536 * ZD_BUF_ERROR if there was not enough room in the output 
537 * buffer. 
538 */ 
539 ZEXTERN int ZEXPORT zd_uncompress OF ((const Bytef *ref, uLong rsize, 
540      Bytef *tar, uLongf *tsize, 
541      const Bytef *delta, uLong dsize)); 

Все переменные размера правильно инициализированы. Всякий раз, когда я запускаю декомпрессию, он segfaults глубоко внутри библиотеки zdelta на memcpy в zdelta/inffast.c, кажется плохим назначением (только за исключением случая, о котором я упоминал выше). У кого-нибудь была эта проблема раньше? Благодаря!

+0

Поскольку у вас есть исходный код, я рекомендую вам перекомпилировать с отладкой, а затем отлаживать против программы. Это должно немедленно определить segfault (при условии, что это не тот тип ошибки, который нарушается из-за существования при включении отладки). Кроме того, попробуйте Valgrind против сборки отладки, чтобы убедиться, что, вероятно, он непослушен в памяти. –

+0

спасибо за отзыв, я действительно решил эту проблему, был (по крайней мере) проблемой переполнения inffast.c. – lzt

ответ

2

Я понял, эта проблема была вызвана отрицанием переменной без знака, в файле inffast.c в строке 138:

ptr = rwptr[best_ptr] + (sign == ZD_PLUS ? d : -d); 

d объявлен типа uInt, поэтому отрицание в ложном часть будет (скорее всего) переполнение, что стало причиной плохого адреса назначения memcpy().

Simply изменения этого в:

if(ZD_PLUS == sign) 
{ 
    ptr = rwptr[best_ptr] + d; 
} 
else 
{ 
    ptr = rwptr[best_ptr] - d; 
} 

Решает вопрос.

Та же самая история для линии 257 в infcodes.c:

c->bp = rwptr[best_ptr] + (c->sign == ZD_PLUS ? c->dist : -c->dist); 
Смежные вопросы