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?