Coverage Report

Created: 2025-07-23 06:33

/src/php-src/ext/standard/fsock.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   +----------------------------------------------------------------------+
3
   | Copyright (c) The PHP Group                                          |
4
   +----------------------------------------------------------------------+
5
   | This source file is subject to version 3.01 of the PHP license,      |
6
   | that is bundled with this package in the file LICENSE, and is        |
7
   | available through the world-wide-web at the following url:           |
8
   | https://www.php.net/license/3_01.txt                                 |
9
   | If you did not receive a copy of the PHP license and are unable to   |
10
   | obtain it through the world-wide-web, please send a note to          |
11
   | license@php.net so we can mail you a copy immediately.               |
12
   +----------------------------------------------------------------------+
13
   | Authors: Paul Panotzki - Bunyip Information Systems                  |
14
   |          Jim Winstead <jimw@php.net>                                 |
15
   |          Sascha Schumann <sascha@schumann.cx>                        |
16
   +----------------------------------------------------------------------+
17
*/
18
19
#include "php.h"
20
#include "php_globals.h"
21
#include <stdlib.h>
22
#include <stddef.h>
23
#include "php_network.h"
24
#include "file.h"
25
26
static size_t php_fsockopen_format_host_port(char **message, const char *prefix, size_t prefix_len,
27
  const char *host, size_t host_len, zend_long port)
28
0
{
29
0
    char portbuf[32];
30
0
    int portlen = snprintf(portbuf, sizeof(portbuf), ":" ZEND_LONG_FMT, port);
31
0
    size_t total_len = prefix_len + host_len + portlen;
32
33
0
    char *result = emalloc(total_len + 1); 
34
35
0
  if (prefix_len > 0) {
36
0
      memcpy(result, prefix, prefix_len);
37
0
  }
38
0
    memcpy(result + prefix_len, host, host_len);
39
0
    memcpy(result + prefix_len + host_len, portbuf, portlen);
40
41
0
    result[total_len] = '\0';
42
43
0
    *message = result;
44
45
0
  return total_len;
46
0
}
47
48
/* {{{ php_fsockopen() */
49
50
static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
51
0
{
52
0
  char *host;
53
0
  size_t host_len;
54
0
  zend_long port = -1;
55
0
  zval *zerrno = NULL, *zerrstr = NULL;
56
0
  double timeout;
57
0
  bool timeout_is_null = 1;
58
0
#ifndef PHP_WIN32
59
0
  time_t conv;
60
#else
61
  long conv;
62
#endif
63
0
  struct timeval tv;
64
0
  char *hashkey = NULL;
65
0
  php_stream *stream = NULL;
66
0
  int err;
67
0
  char *hostname = NULL;
68
0
  size_t hostname_len;
69
0
  zend_string *errstr = NULL;
70
71
0
  ZEND_PARSE_PARAMETERS_START(1, 5)
72
0
    Z_PARAM_STRING(host, host_len)
73
0
    Z_PARAM_OPTIONAL
74
0
    Z_PARAM_LONG(port)
75
0
    Z_PARAM_ZVAL(zerrno)
76
0
    Z_PARAM_ZVAL(zerrstr)
77
0
    Z_PARAM_DOUBLE_OR_NULL(timeout, timeout_is_null)
78
0
  ZEND_PARSE_PARAMETERS_END();
79
80
0
  RETVAL_FALSE;
81
82
0
  if (timeout_is_null) {
83
0
    timeout = (double)FG(default_socket_timeout);
84
0
  }
85
86
0
  if (persistent) {
87
0
    php_fsockopen_format_host_port(&hashkey, "pfsockopen__", strlen("pfsockopen__"), host,
88
0
        host_len, port);
89
0
  }
90
91
0
  if (port > 0) {
92
0
    hostname_len = php_fsockopen_format_host_port(&hostname, "", 0, host, host_len, port);
93
0
  } else {
94
0
    hostname_len = host_len;
95
0
    hostname = host;
96
0
  }
97
98
  /* prepare the timeout value for use */
99
0
  if (timeout != -1.0 && !(timeout >= 0.0 && timeout <= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0)) {
100
0
    if (port > 0) {
101
0
      efree(hostname);
102
0
    }
103
104
0
    if (hashkey) {
105
0
      efree(hashkey);
106
0
    }
107
108
0
    zend_argument_value_error(6, "must be -1 or between 0 and " ZEND_ULONG_FMT, ((double) PHP_TIMEOUT_ULL_MAX / 1000000.0));
109
0
    RETURN_THROWS();
110
0
  } else {
111
0
#ifndef PHP_WIN32
112
0
    conv = (time_t) (timeout * 1000000.0);
113
0
    tv.tv_sec = conv / 1000000;
114
#else
115
    conv = (long) (timeout * 1000000.0);
116
    tv.tv_sec = conv / 1000000;
117
#endif
118
0
    tv.tv_usec = conv % 1000000;
119
0
  }
120
121
0
  stream = php_stream_xport_create(hostname, hostname_len, REPORT_ERRORS,
122
0
      STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, hashkey, &tv, NULL, &errstr, &err);
123
124
0
  if (port > 0) {
125
0
    efree(hostname);
126
0
  }
127
0
  if (stream == NULL) {
128
0
    php_error_docref(NULL, E_WARNING, "Unable to connect to %s:" ZEND_LONG_FMT " (%s)", host, port, errstr == NULL ? "Unknown error" : ZSTR_VAL(errstr));
129
0
  }
130
131
0
  if (hashkey) {
132
0
    efree(hashkey);
133
0
  }
134
135
0
  if (stream == NULL) {
136
0
    if (zerrno) {
137
0
      ZEND_TRY_ASSIGN_REF_LONG(zerrno, err);
138
0
    }
139
0
    if (errstr) {
140
0
      if (zerrstr) {
141
0
        ZEND_TRY_ASSIGN_REF_STR(zerrstr, errstr);
142
0
      } else {
143
0
        zend_string_release(errstr);
144
0
      }
145
0
    }
146
147
0
    RETURN_FALSE;
148
0
  }
149
150
0
  if (zerrno) {
151
0
    ZEND_TRY_ASSIGN_REF_LONG(zerrno, 0);
152
0
  }
153
0
  if (zerrstr) {
154
0
    ZEND_TRY_ASSIGN_REF_EMPTY_STRING(zerrstr);
155
0
  }
156
157
0
  if (errstr) {
158
0
    zend_string_release_ex(errstr, 0);
159
0
  }
160
161
0
  php_stream_to_zval(stream, return_value);
162
0
}
163
164
/* }}} */
165
166
/* {{{ Open Internet or Unix domain socket connection */
167
PHP_FUNCTION(fsockopen)
168
0
{
169
0
  php_fsockopen_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
170
0
}
171
/* }}} */
172
173
/* {{{ Open persistent Internet or Unix domain socket connection */
174
PHP_FUNCTION(pfsockopen)
175
0
{
176
0
  php_fsockopen_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
177
0
}
178
/* }}} */