php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #29431 segfault using stream_* with UDP
Submitted: 2004-07-28 17:31 UTC Modified: 2004-07-31 13:43 UTC
From: nlopess@php.net Assigned:
Status: Closed Package: Network related
PHP Version: 5.1.0-cvs OS: Linux 2.4
Private report: No CVE-ID:
 [2004-07-28 17:31 UTC] nlopess@php.net
Description:
------------
PHP 5 HEAD segfaults with the given code.
Below are URLs with valgrind/gdb output.

Reproduce code:
---------------
<?
$socket = stream_socket_server("udp://127.0.0.1:13", $errno, $errstr, STREAM_SERVER_BIND);
if (!$socket)
	die("$errstr ($errno)");

do {
   $pkt = stream_socket_recvfrom($socket, 1, 0, $peer);
   stream_socket_sendto($socket, date("D M j H:i:s Y\r\n"), 0, $peer);
} while ($pkt !== false);

?>

Actual result:
--------------
http://testes.aborla.net/gdb.txt
http://testes.aborla.net/out.pid7736

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-07-29 01:00 UTC] wez@php.net
Does it segfault if you disable the sockets extension?
(Looking into your script now, but the valgrind output indicates that ext/sockets is still a bad choice)
 [2004-07-29 01:31 UTC] wez@php.net
Fixed in HEAD.
 [2004-07-30 18:13 UTC] nlopess@php.net
It doesn't segfault, but... doesn't work.
I think stream_socket_recvfrom() ins't populating $peer


"Warning: stream_socket_sendto()]: Invalid argument in /transfer/a.php on line 11"


gdb output:

Program received signal SIGINT, Interrupt.
0x4037e6c2 in select () from /lib/libc.so.6
(gdb) bt
#0  0x4037e6c2 in select () from /lib/libc.so.6
#1  0x082beddc in __JCR_LIST__ ()
#2  0xbfffd2b8 in ?? ()
#3  0xbfffd340 in ?? ()
#4  0x081c9c3d in php_sock_stream_wait_for_data (stream=0x836e95c,
    sock=0x83640cc) at /cvs/php-src/main/streams/xp_socket.c:100
#5  0x081c9c8f in php_sockop_read (stream=0x836e95c, buf=0x836eb14 "",
    count=8192) at /cvs/php-src/main/streams/xp_socket.c:120
#6  0x081c191e in php_stream_fill_read_buffer (stream=0x836e95c, size=1)
    at /cvs/php-src/main/streams/streams.c:530
#7  0x081c1c34 in _php_stream_read (stream=0x836e95c, buf=0x836412c "", size=1)
    at /cvs/php-src/main/streams/streams.c:573
#8  0x081c998f in php_stream_xport_recvfrom (stream=0x836e95c,
    buf=0x836412c "", buflen=1, flags=0, addr=0x0, addrlen=0xfffffdfe,
    textaddr=0x836ea44, textaddrlen=0xfffffdfe)
    at /cvs/php-src/main/streams/transports.c:391
#9  0x081a4fee in zif_stream_socket_recvfrom (ht=4, return_value=0x8370b7c,
    this_ptr=0x0, return_value_used=1)
    at /cvs/php-src/ext/standard/streamsfuncs.c:328
#10 0x082096d9 in zend_do_fcall_common_helper (execute_data=0xbfffd630,
    opline=0x837322c, op_array=0x836e88c)
    at /cvs/php-src/Zend/zend_execute.c:2699
#11 0x0820983a in zend_do_fcall_handler (execute_data=0xbfffd630,
    opline=0x837322c, op_array=0x836e88c)
    at /cvs/php-src/Zend/zend_execute.c:2831
#12 0x08206068 in execute (op_array=0x836e88c)
    at /cvs/php-src/Zend/zend_execute.c:1391
#13 0x081e9dca in zend_execute_scripts (type=8, retval=0x0, file_count=3)
    at /cvs/php-src/Zend/zend.c:1068
#14 0x081b4440 in php_execute_script (primary_file=0xbffffa00)
    at /cvs/php-src/main/main.c:1631
#15 0x08210f80 in main (argc=2, argv=0xbffffa94)
    at /cvs/php-src/sapi/cli/php_cli.c:943
 [2004-07-30 19:23 UTC] wez@php.net
Works flawlessly here; are you sure you're running head?

udp.php:
<?php
$socket = stream_socket_server("udp://127.0.0.1:1113", $errno, $errstr, STREAM_SERVER_BIND);
if (!$socket)
       die("$errstr ($errno)");

do {
  $pkt = stream_socket_recvfrom($socket, 1, 0, $peer);
  print_r($pkt);
  print_r($peer);
  stream_socket_sendto($socket, date("D M j H:i:s Y\r\n"), 0, $peer);
} while ($pkt !== false);

?>

% php udp.php &
% php -r '$f = fsockopen("udp://127.0.0.1", 1113); fwrite($f, 'x'); var_dump(fgets($f));'


 [2004-07-30 21:05 UTC] nlopess@php.net
Yep!

I've done a cvsclean (and a cvs update) and re-compiled everything, and still get the same backtrace/error.
 [2004-07-31 12:06 UTC] wez@php.net
Please try the script I posted.
Paste it's output.
If it doesn't work, run it using:

strace -e trace=net php udp.php

and paste that output too.
 [2004-07-31 12:25 UTC] nlopess@php.net
# strace -e trace=network php udp.php

socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = -1 EAFNOSUPPORT (Address family not supported by protocol)
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(1113), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
recv(3, "x", 8192, 0)                   = 1
xsendto(3, "Sat Jul 31 10:34:20 2004\r\n", 26, 0, {sa_family=0x3032 /* AF_??? */
, sa_data="04\0\0\0\0\24\325\377\277\2568)@"}, 0) = -1 EINVAL (Invalid argument)


Warning: stream_socket_sendto() [/manual/function.stream-socket-sendto.html]: In
valid argument
 in /transfer/udp.php on line 10



It just outputs 'x', so $peer is empty.
 [2004-07-31 13:03 UTC] wez@php.net
Looks like I forgot to commit some changes;
should be fixed now in both HEAD and 5.0 branches.
 [2004-07-31 13:16 UTC] nlopess@php.net
The problem is fixed! Thanks!!!

But valgrind still complains... Not sure if it's related with streams, but:

==14229== 18 bytes in 1 blocks are still reachable in loss record 1 of 3
==14229==    at 0x40026BB2: malloc (vg_replace_malloc.c:153)
==14229==    by 0x4058638B: inet_ntoa (in /lib/libc-2.3.3.so)
==14229==    by 0x81BE8BE: php_network_populate_name_from_sockaddr (network.c:593)
==14229==    by 0x81CA06C: php_sockop_set_option (xp_socket.c:223)
==14229==    by 0x81C27BB: _php_stream_set_option (streams.c:1110)
==14229==    by 0x81C988A: php_stream_xport_recvfrom (transports.c:433)
==14229==    by 0x81A4FED: zif_stream_socket_recvfrom (streamsfuncs.c:328)
==14229==    by 0x8209810: zend_do_fcall_common_helper (zend_execute.c:2699)
==14229==    by 0x82099FE: zend_do_fcall_handler (zend_execute.c:2831)
==14229==    by 0x8205FF7: execute (zend_execute.c:1391)
==14229==    by 0x81E9D59: zend_execute_scripts (zend.c:1068)
==14229==    by 0x81B443F: php_execute_script (main.c:1631)
==14229==    by 0x821118F: main (php_cli.c:943)
==14229==    by 0x404E1858: __libc_start_main (in /lib/libc-2.3.3.so)
==14229==    by 0x8080550: (within /usr/local/bin/php)
==14229== 
==14229== 
==14229== 100 bytes in 1 blocks are still reachable in loss record 2 of 3
==14229==    at 0x40026BB2: malloc (vg_replace_malloc.c:153)
==14229==    by 0x81D353B: yy_flex_alloc (zend_language_scanner.c:6260)
==14229==    by 0x81D33DB: yy_push_state (zend_language_scanner.c:6149)
==14229==    by 0x81D0B02: lex_scan (zend_language_scanner.l:1152)
==14229==    by 0x81DDE90: zendlex (zend_compile.c:3682)
==14229==    by 0x81CEE8C: zendparse (zend_language_parser.c:2632)
==14229==    by 0x81CF2F2: compile_file (zend_language_scanner.l:375)
==14229==    by 0x81E9D21: zend_execute_scripts (zend.c:1064)
==14229==    by 0x81B443F: php_execute_script (main.c:1631)
==14229==    by 0x821118F: main (php_cli.c:943)
==14229==    by 0x404E1858: __libc_start_main (in /lib/libc-2.3.3.so)
==14229==    by 0x8080550: (within /usr/local/bin/php)
 [2004-07-31 13:43 UTC] wez@php.net
Nope, not a PHP; that indicates that inet_ntoa has a memory leak.  However:

man inet_ntoa -->
The inet_ntoa() function converts the Internet host address
in given in network byte order to a string in standard
numbers-and-dots notation.  The string is returned in a
statically allocated buffer, which  subsequent  calls  will
overwrite.

It's not PHP's responsibility to clean that up, and most likely it's something that valgrind should suppress anyway, and its only 18 bytes ;-)
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 16 10:02:09 2014 UTC