64bit UnixODBC e FreeTDS: um bug no libtdsodbc.so?

1

Temos um aplicativo Web Windows legado que usa o Microsoft SQL Server 2005. Há dois anos, reescrevemos uma parte desse aplicativo usando PHP e ODBC em um sistema Debian virtualizado de 32 bits. Este aplicativo funciona bem (cerca de uma solicitação SQL de mil produz dados falsos, mas isso é tratado pelo aplicativo). Os pacotes Debian usados são: php5-odbc, odbcinst1debian1, tdsodbc, unixodbc, freetds-common.

Agora queremos desvirtualizar isso e instalar o aplicativo como um host virtual Apache em um sistema Debian Lenny de 64 bits. Mas algo ruim acontece na função PHP odbc_fetch_object (). Eu tenho

echo "Before odbc_fetch_object(); $query\n"; flush();
if ($query) $row = odbc_fetch_object($query);
echo "After odbc_fetch_object();\n"; flush();
echo "Edition number $row->Id\n";

mas o texto "After odbc_fetch_object ()" e o texto seguinte nunca são mostrados.

Eu depurei o arquivo PHP chamando-o pelo php5 diretamente (pacote php5-cli). Desta vez, ele realmente obtém dados do banco de dados (o número da edição atual que muda a cada semana). Mas depois da saída eu recebo a string da mensagem de erro

ALERT - canary mismatch on efree() - heap overflow detected (attacker 'REMOTE_ADDR not set', file 'unknown')

Você deve saber que o Debian PHP5 está integrado com o patch Suhosin. Parece que descobre corrupção de memória em odbc_fetch_object ().

Nós tentamos depurar com o valgrind com alocação de memória suprimida do Zend:

USE_ZEND_ALLOC=0 valgrind --leak-check=full ./current.php

e obteve a seguinte saída:

==3831== Memcheck, a memory error detector.
==3831== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==3831== Using LibVEX rev 1854, a library for dynamic binary translation.
==3831== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==3831== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation framework.
==3831== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==3831== For more details, rerun with: -v
==3831== 
==3831== Invalid write of size 8
==3831==    at 0xD64420C: (within /usr/lib/odbc/libtdsodbc.so)
==3831==    by 0xB55E859: SQLColAttributes (in /usr/lib/libodbc.so.1.0.0)
==3831==    by 0xB34AA37: odbc_bindcols (in /usr/lib/php5/20060613/odbc.so)
==3831==    by 0xB350B86: zif_odbc_exec (in /usr/lib/php5/20060613/odbc.so)
==3831==    by 0xBDEDC9C: (within /usr/lib/php5/20060613/suhosin.so)
==3831==    by 0x6A5798: (within /usr/bin/php5)
==3831==    by 0x691003: execute (in /usr/bin/php5)
==3831==    by 0xBDEE125: (within /usr/lib/php5/20060613/suhosin.so)
==3831==    by 0x66CDF7: zend_execute_scripts (in /usr/bin/php5)
==3831==    by 0x627667: php_execute_script (in /usr/bin/php5)
==3831==    by 0x6EBFF6: main (in /usr/bin/php5)
==3831==  Address 0xd2b564c is 44 bytes inside a block of size 48 alloc'd
==3831==    at 0x4C2260E: malloc (vg_replace_malloc.c:207)
==3831==    by 0xB34A911: odbc_bindcols (in /usr/lib/php5/20060613/odbc.so)
==3831==    by 0xB350B86: zif_odbc_exec (in /usr/lib/php5/20060613/odbc.so)
==3831==    by 0xBDEDC9C: (within /usr/lib/php5/20060613/suhosin.so)
==3831==    by 0x6A5798: (within /usr/bin/php5)
==3831==    by 0x691003: execute (in /usr/bin/php5)
==3831==    by 0xBDEE125: (within /usr/lib/php5/20060613/suhosin.so)
==3831==    by 0x66CDF7: zend_execute_scripts (in /usr/bin/php5)
==3831==    by 0x627667: php_execute_script (in /usr/bin/php5)
==3831==    by 0x6EBFF6: main (in /usr/bin/php5)
Before odbc_fetch_object(): Resource id #6 
After odbc_fetch_object()
Edition number 547
Some static text
==3831== 
==3831== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 531 from 4)
==3831== malloc/free: in use at exit: 58,755 bytes in 1,558 blocks.
==3831== malloc/free: 22,559 allocs, 21,001 frees, 3,867,219 bytes allocated.
==3831== For counts of detected errors, rerun with: -v
==3831== searching for pointers to 1,558 not-freed blocks.
==3831== checked 1,223,080 bytes.
==3831== 
==3831== 
==3831== 2 bytes in 1 blocks are definitely lost in loss record 1 of 24
==3831==    at 0x4C2260E: malloc (vg_replace_malloc.c:207)
==3831==    by 0x7609D91: strdup (in /lib/libc-2.7.so)
==3831==    by 0xBDDF74B: ???
==3831==    by 0x68199D: zend_register_ini_entries (in /usr/bin/php5)
==3831==    by 0xBDDFBCF: ???
==3831==    by 0x6732DA: zend_startup_module_ex (in /usr/bin/php5)
==3831==    by 0x67828A: zend_hash_apply (in /usr/bin/php5)
==3831==    by 0x671B59: zend_startup_modules (in /usr/bin/php5)
==3831==    by 0x628E22: php_module_startup (in /usr/bin/php5)
==3831==    by 0x6EA71C: (within /usr/bin/php5)
==3831==    by 0x6EAF31: main (in /usr/bin/php5)
==3831== 
==3831== 
==3831== 292 (52 direct, 240 indirect) bytes in 1 blocks are definitely lost in loss record 11 of 24
==3831==    at 0x4C2260E: malloc (vg_replace_malloc.c:207)
==3831==    by 0x766D52F: (within /lib/libc-2.7.so)
==3831==    by 0x766DD06: __nss_database_lookup (in /lib/libc-2.7.so)
==3831==    by 0xCC2631F: ???
==3831==    by 0xCC2702C: ???
==3831==    by 0x762C101: getpwuid_r (in /lib/libc-2.7.so)
==3831==    by 0x762B9CE: getpwuid (in /lib/libc-2.7.so)
==3831==    by 0xB59C2EF: ???
==3831==    by 0xB599B2B: ???
==3831==    by 0xB58A013: ???
==3831==    by 0xB56307F: ???
==3831==    by 0xB34896D: ???
==3831== 
==3831== 
==3831== 512 bytes in 1 blocks are definitely lost in loss record 17 of 24
==3831==    at 0x4C22741: realloc (vg_replace_malloc.c:429)
==3831==    by 0x678AC8: (within /usr/bin/php5)
==3831==    by 0x678B44: (within /usr/bin/php5)
==3831==    by 0x67AEF7: _zend_hash_add_or_update (in /usr/bin/php5)
==3831==    by 0xBDED02C: ???
==3831==    by 0xBDDE995: ???
==3831==    by 0x677690: (within /usr/bin/php5)
==3831==    by 0x6634B1: zend_llist_apply_with_del (in /usr/bin/php5)
==3831==    by 0x677676: zend_startup_extensions (in /usr/bin/php5)
==3831==    by 0x628E5B: php_module_startup (in /usr/bin/php5)
==3831==    by 0x6EA71C: (within /usr/bin/php5)
==3831==    by 0x6EAF31: main (in /usr/bin/php5)
==3831== 
==3831== LEAK SUMMARY:
==3831==    definitely lost: 566 bytes in 3 blocks.
==3831==    indirectly lost: 240 bytes in 10 blocks.
==3831==      possibly lost: 0 bytes in 0 blocks.
==3831==    still reachable: 57,949 bytes in 1,545 blocks.
==3831==         suppressed: 0 bytes in 0 blocks.
==3831== Reachable blocks (those to which a pointer was found) are not shown.
==3831== To see them, rerun with: --leak-check=full --show-reachable=yes

Você pode sugerir uma solução alternativa para algo que parece ser um erro de alocação de memória na biblioteca libtdsodbc.so? Ou você tem uma ideia do que poderíamos fazer, exceto obter o código-fonte e consertar o bug?

    
por nalply 02.12.2009 / 10:10

3 respostas

1

Hmm, parece que há mais erros de 64 bits no driver PHP odbc. Eu relatei este bug para redhat alguns anos atrás ; que era para o PHP 4.3.x no RHEL4, e naquela época ele já estava corrigido no upstream, então presumivelmente o Debian Lenny já tem a versão corrigida.

Além de consertar você mesmo, ou pelo menos arquivar relatórios de bug no upstream e, entretanto, não usar o php-odbc em plataformas de 64 bits, não tenho nenhum conselho melhor. Desculpe.

EDIT: Uma coisa que você pode tentar, é não usar o ODBC, mas sim a interface TDS diretamente. Embora eu não tenha certeza se existe uma interface TDS de nível PHP, mas você pode fazer isso pelo menos se você usar a interface de banco de dados PHP PDO que está disponível no PHP 5.x. Veja o módulo PDO_DBLIB.

    
por 02.12.2009 / 10:35
0

Eu enviei um e-mail para três desenvolvedores no link , enviei um relatório de bug no PHP link e no Debian (postará o número mais tarde).

Para nós, é tarde demais. Vamos cancelar este projeto, mas espero que os desenvolvedores possam consertar o bug para que os outros não sejam parados tão brutalmente como nós.

    
por 03.12.2009 / 10:10
0

O bug em não presente no PHP 5.2.7 causa a mudança de len de SDWORD para o tipo SQLLEN correto, que é de 64 bits para plataformas de 64 bits.

Cumprimentos   Frediano Ziglio   (também conhecido como freddy77)

    
por 04.12.2009 / 10:38