Sunday November 13 2016 09:10, from Peter Khanin -> All:
PK> Мастер как бы падает, но редко. А Binkd 1.0.5-pre5 с тем же болтом в PK> defnode...
А я тут погонял binkd последний из cvs с Perl хуком для нодлиста, под valgrind, много интересного. Много глюков связано с конфигом и его перечитыванием. Ну ладно, что "деструктор" не вычищает всю аллоцируемую память, это просто вопрос стиля чтоли.
Вот это уже более серьёздно. Например, во free_nodes() освобождается xfree(node->pipe); Но у меня в конфигах нет ни каких пайпов ни разу.
==21674== Invalid free() / delete / delete[] / realloc() ==21674== at 0x4C2BD57: free (vg_replace_malloc.c:530) ==21674== by 0x42AD62: xfree (xalloc.c:60) ==21674== by 0x42759C: free_nodes (ftnnode.c:409) ==21674== by 0x40950C: unlock_config_structure (readcfg.c:262) ==21674== by 0x415AE7: clientmgr (client.c:258) ==21674== by 0x4261E4: branch (branch.c:87) ==21674== by 0x408F0B: main (binkd.c:721) ==21674== Address 0x6ccf110 is 0 bytes inside a block of size 1 free'd ==21674== at 0x4C2BD57: free (vg_replace_malloc.c:530) ==21674== by 0x42AD62: xfree (xalloc.c:60) ==21674== by 0x42759C: free_nodes (ftnnode.c:409) ==21674== by 0x40950C: unlock_config_structure (readcfg.c:262) ==21674== by 0x415AE7: clientmgr (client.c:258) ==21674== by 0x4261E4: branch (branch.c:87) ==21674== by 0x408F0B: main (binkd.c:721) ==21674== Block was alloc'd at ==21674== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299) ==21674== by 0x42ABEA: xalloc (xalloc.c:21) ==21674== by 0x42ACA5: xstrdup (xalloc.c:42) ==21674== by 0x426864: add_node_nolock (ftnnode.c:139) ==21674== by 0x426B32: add_node (ftnnode.c:202) ==21674== by 0x40B72E: read_node_info (readcfg.c:1237) ==21674== by 0x40A16A: readcfg0 (readcfg.c:724) ==21674== by 0x40A256: readcfg (readcfg.c:747) ==21674== by 0x40A681: checkcfg (readcfg.c:890) ==21674== by 0x415B1E: clientmgr (client.c:274) ==21674== by 0x4261E4: branch (branch.c:87) ==21674== by 0x408F0B: main (binkd.c:721)
Или вот прикол ещё, при звонке на не стандартный порт (г-н Пушкин, хостит /2140 на дефолтовом, а вот /2141 на 24555), в функцию srv_getaddrinfo() передаётся поинтер на левую память в service, и там atoi() падает.
==8538== Invalid read of size 1 ==8538== at 0x56365B4: ____strtol_l_internal (strtol_l.c:438) ==8538== by 0x5632EAF: atoi (atoi.c:27) ==8538== by 0x44E44B: srv_getaddrinfo (srv_gai.c:80) ==8538== by 0x417429: call0 (client.c:429) ==8538== by 0x417EC6: call (client.c:647) ==8538== by 0x427A36: branch (branch.c:87) ==8538== by 0x416A83: do_client (client.c:146) ==8538== by 0x416DED: clientmgr (client.c:265) ==8538== by 0x427A36: branch (branch.c:87) ==8538== by 0x409121: main (binkd.c:721) ==8538== Address 0x71cdc20 is 16 bytes inside a block of size 21 free'd ==8538== at 0x4C2BD57: free (vg_replace_malloc.c:530) ==8538== by 0x40BF80: get_host_and_port (readcfg.c:1300) ==8538== by 0x417C53: call0 (client.c:392) ==8538== by 0x417EC6: call (client.c:647) ==8538== by 0x427A36: branch (branch.c:87) ==8538== by 0x416A83: do_client (client.c:146) ==8538== by 0x416DED: clientmgr (client.c:265) ==8538== by 0x427A36: branch (branch.c:87) ==8538== by 0x409121: main (binkd.c:721) ==8538== Block was alloc'd at ==8538== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299) ==8538== by 0x42CB7B: xalloc (xalloc.c:21) ==8538== by 0x42CC82: xstrdup (xalloc.c:42) ==8538== by 0x42C593: getwordx2 (getw.c:22) ==8538== by 0x40BE47: get_host_and_port (readcfg.c:1266) ==8538== by 0x417C53: call0 (client.c:392) ==8538== by 0x417EC6: call (client.c:647) ==8538== by 0x427A36: branch (branch.c:87) ==8538== by 0x416A83: do_client (client.c:146) ==8538== by 0x416DED: clientmgr (client.c:265) ==8538== by 0x427A36: branch (branch.c:87) ==8538== by 0x409121: main (binkd.c:721)
Волшебная функция get_host_and_port(), получает для переменной s память внутри getwordx2(src, ..), ну и в конце честно делает free (s), только вот возвращает в port адрес на часть подстроки из s, вот тут *port = find_port(), и память уже тут не валидная.
Я думал щас быстренько патчик выпущу на все тут найденные приколы (а их много), но сдался, тут сложно понять идеалогию кто чем владеет, постоянно делается strdup(), указатель потом освобождается где-то в совсем другом месте, или вовсе не осбобождается (пофиг, главное не падает). Ну и там srcpy(), strcat() без проверки на границы.
Я такой код починить не могу, проще написать на C++, чтобы стринги владели памятью. Листы на STL'ные контейнеры если заменить, то весь бойлерплейт тоже уйдёт. Если дропнуть совместимость с экзотикой, или сказать, что мы собираем везде, где поддерживается C++11 (уже многое из 17го поддерживается современными компиляторами), то уйдёт весь этот развесистый код.