Coverage Report

Created: 2025-12-31 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/standard/basic_functions.c
Line
Count
Source
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: Andi Gutmans <andi@php.net>                                 |
14
   |          Zeev Suraski <zeev@php.net>                                 |
15
   +----------------------------------------------------------------------+
16
 */
17
18
#include "php.h"
19
#include "php_assert.h"
20
#include "php_crypt.h"
21
#include "php_streams.h"
22
#include "php_main.h"
23
#include "php_globals.h"
24
#include "php_variables.h"
25
#include "php_ini.h"
26
#include "php_image.h"
27
#include "php_standard.h"
28
#include "php_math.h"
29
#include "php_http.h"
30
#include "php_incomplete_class.h"
31
#include "php_getopt.h"
32
#include "php_ext_syslog.h"
33
#include "ext/standard/info.h"
34
#include "ext/session/php_session.h"
35
#include "zend_exceptions.h"
36
#include "zend_attributes.h"
37
#include "zend_enum.h"
38
#include "zend_ini.h"
39
#include "zend_operators.h"
40
#include "ext/standard/php_dns.h"
41
#include "ext/standard/php_uuencode.h"
42
#include "ext/standard/crc32_x86.h"
43
44
#ifdef PHP_WIN32
45
#include "win32/php_win32_globals.h"
46
#include "win32/time.h"
47
#include "win32/ioutil.h"
48
#endif
49
50
typedef struct yy_buffer_state *YY_BUFFER_STATE;
51
52
#include "zend.h"
53
#include "zend_ini_scanner.h"
54
#include "zend_language_scanner.h"
55
#include <zend_language_parser.h>
56
57
#include "zend_portability.h"
58
59
#include <stdarg.h>
60
#include <stdlib.h>
61
#include <math.h>
62
#include <time.h>
63
#include <stdio.h>
64
65
#ifndef PHP_WIN32
66
#include <sys/types.h>
67
#include <sys/stat.h>
68
#endif
69
70
#ifndef PHP_WIN32
71
# include <netdb.h>
72
#endif
73
74
#ifdef HAVE_ARPA_INET_H
75
# include <arpa/inet.h>
76
#endif
77
78
#ifdef HAVE_UNISTD_H
79
# include <unistd.h>
80
#endif
81
82
#include <string.h>
83
#include <locale.h>
84
#ifdef HAVE_LANGINFO_H
85
# include <langinfo.h>
86
#endif
87
88
#ifdef HAVE_SYS_MMAN_H
89
# include <sys/mman.h>
90
#endif
91
92
#ifdef HAVE_SYS_LOADAVG_H
93
# include <sys/loadavg.h>
94
#endif
95
96
#ifdef PHP_WIN32
97
# include "win32/unistd.h"
98
#endif
99
100
#ifndef INADDR_NONE
101
# define INADDR_NONE ((zend_ulong) -1)
102
#endif
103
104
#include "zend_globals.h"
105
#include "php_globals.h"
106
#include "SAPI.h"
107
#include "php_ticks.h"
108
109
#ifdef ZTS
110
PHPAPI int basic_globals_id;
111
#else
112
PHPAPI php_basic_globals basic_globals;
113
#endif
114
115
#include "php_fopen_wrappers.h"
116
#include "streamsfuncs.h"
117
#include "zend_frameless_function.h"
118
#include "basic_functions_arginfo.h"
119
120
#if __has_feature(memory_sanitizer)
121
# include <sanitizer/msan_interface.h>
122
#endif
123
124
typedef struct _user_tick_function_entry {
125
  zend_fcall_info_cache fci_cache;
126
  zval *params;
127
  uint32_t param_count;
128
  bool calling;
129
} user_tick_function_entry;
130
131
#ifdef HAVE_PUTENV
132
typedef struct {
133
  char *putenv_string;
134
  char *previous_value;
135
  zend_string *key;
136
} putenv_entry;
137
#endif
138
139
/* some prototypes for local functions */
140
static void user_shutdown_function_dtor(zval *zv);
141
static void user_tick_function_dtor(user_tick_function_entry *tick_function_entry);
142
143
static const zend_module_dep standard_deps[] = { /* {{{ */
144
  ZEND_MOD_REQUIRED("uri")
145
  ZEND_MOD_OPTIONAL("session")
146
  ZEND_MOD_END
147
};
148
/* }}} */
149
150
zend_module_entry basic_functions_module = { /* {{{ */
151
  STANDARD_MODULE_HEADER_EX,
152
  NULL,
153
  standard_deps,
154
  "standard",         /* extension name */
155
  ext_functions,        /* function list */
156
  PHP_MINIT(basic),     /* process startup */
157
  PHP_MSHUTDOWN(basic),   /* process shutdown */
158
  PHP_RINIT(basic),     /* request startup */
159
  PHP_RSHUTDOWN(basic),   /* request shutdown */
160
  PHP_MINFO(basic),     /* extension info */
161
  PHP_STANDARD_VERSION,   /* extension version */
162
  STANDARD_MODULE_PROPERTIES
163
};
164
/* }}} */
165
166
#ifdef HAVE_PUTENV
167
static void php_putenv_destructor(zval *zv) /* {{{ */
168
0
{
169
0
  putenv_entry *pe = Z_PTR_P(zv);
170
171
0
  if (pe->previous_value) {
172
# ifdef PHP_WIN32
173
    /* MSVCRT has a bug in putenv() when setting a variable that
174
     * is already set; if the SetEnvironmentVariable() API call
175
     * fails, the Crt will double free() a string.
176
     * We try to avoid this by setting our own value first */
177
    SetEnvironmentVariable(ZSTR_VAL(pe->key), "bugbug");
178
# endif
179
0
    putenv(pe->previous_value);
180
# ifdef PHP_WIN32
181
    efree(pe->previous_value);
182
# endif
183
0
  } else {
184
0
# ifdef HAVE_UNSETENV
185
0
    unsetenv(ZSTR_VAL(pe->key));
186
# elif defined(PHP_WIN32)
187
    SetEnvironmentVariable(ZSTR_VAL(pe->key), NULL);
188
# ifndef ZTS
189
    _putenv_s(ZSTR_VAL(pe->key), "");
190
# endif
191
# else
192
    char **env;
193
194
    for (env = environ; env != NULL && *env != NULL; env++) {
195
      if (!strncmp(*env, ZSTR_VAL(pe->key), ZSTR_LEN(pe->key))
196
          && (*env)[ZSTR_LEN(pe->key)] == '=') {  /* found it */
197
        *env = "";
198
        break;
199
      }
200
    }
201
# endif
202
0
  }
203
0
#ifdef HAVE_TZSET
204
  /* don't forget to reset the various libc globals that
205
   * we might have changed by an earlier call to tzset(). */
206
0
  if (zend_string_equals_literal_ci(pe->key, "TZ")) {
207
0
    tzset();
208
0
  }
209
0
#endif
210
211
0
  free(pe->putenv_string);
212
0
  zend_string_release(pe->key);
213
0
  efree(pe);
214
0
}
215
/* }}} */
216
#endif
217
218
static void basic_globals_ctor(php_basic_globals *basic_globals_p) /* {{{ */
219
14
{
220
14
  memset(basic_globals_p, 0, sizeof(php_basic_globals));
221
222
14
  basic_globals_p->umask = -1;
223
14
  basic_globals_p->url_adapt_session_ex.type = 1;
224
225
14
  zend_hash_init(&basic_globals_p->url_adapt_session_hosts_ht, 0, NULL, NULL, 1);
226
14
  zend_hash_init(&basic_globals_p->url_adapt_output_hosts_ht, 0, NULL, NULL, 1);
227
228
14
  basic_globals_p->page_uid = -1;
229
14
  basic_globals_p->page_gid = -1;
230
14
}
231
/* }}} */
232
233
static void basic_globals_dtor(php_basic_globals *basic_globals_p) /* {{{ */
234
0
{
235
0
  if (basic_globals_p->url_adapt_session_ex.tags) {
236
0
    zend_hash_destroy(basic_globals_p->url_adapt_session_ex.tags);
237
0
    free(basic_globals_p->url_adapt_session_ex.tags);
238
0
  }
239
0
  if (basic_globals_p->url_adapt_output_ex.tags) {
240
0
    zend_hash_destroy(basic_globals_p->url_adapt_output_ex.tags);
241
0
    free(basic_globals_p->url_adapt_output_ex.tags);
242
0
  }
243
244
0
  zend_hash_destroy(&basic_globals_p->url_adapt_session_hosts_ht);
245
0
  zend_hash_destroy(&basic_globals_p->url_adapt_output_hosts_ht);
246
0
}
247
/* }}} */
248
249
PHPAPI double php_get_nan(void) /* {{{ */
250
0
{
251
0
  return ZEND_NAN;
252
0
}
253
/* }}} */
254
255
PHPAPI double php_get_inf(void) /* {{{ */
256
0
{
257
0
  return ZEND_INFINITY;
258
0
}
259
/* }}} */
260
261
#define BASIC_MINIT_SUBMODULE(module) \
262
238
  if (PHP_MINIT(module)(INIT_FUNC_ARGS_PASSTHRU) != SUCCESS) {\
263
0
    return FAILURE; \
264
0
  }
265
266
#define BASIC_RINIT_SUBMODULE(module) \
267
445k
  PHP_RINIT(module)(INIT_FUNC_ARGS_PASSTHRU);
268
269
#define BASIC_MINFO_SUBMODULE(module) \
270
3
  PHP_MINFO(module)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
271
272
#define BASIC_RSHUTDOWN_SUBMODULE(module) \
273
1.33M
  PHP_RSHUTDOWN(module)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
274
275
#define BASIC_MSHUTDOWN_SUBMODULE(module) \
276
0
  PHP_MSHUTDOWN(module)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
277
278
PHP_MINIT_FUNCTION(basic) /* {{{ */
279
14
{
280
#ifdef ZTS
281
  ts_allocate_id(&basic_globals_id, sizeof(php_basic_globals), (ts_allocate_ctor) basic_globals_ctor, (ts_allocate_dtor) basic_globals_dtor);
282
# ifdef PHP_WIN32
283
  ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor)php_win32_core_globals_ctor, (ts_allocate_dtor)php_win32_core_globals_dtor );
284
# endif
285
#else
286
14
  basic_globals_ctor(&basic_globals);
287
# ifdef PHP_WIN32
288
  php_win32_core_globals_ctor(&the_php_win32_core_globals);
289
# endif
290
14
#endif
291
292
14
  register_basic_functions_symbols(module_number);
293
294
14
  php_ce_incomplete_class = register_class___PHP_Incomplete_Class();
295
14
  php_register_incomplete_class_handlers();
296
297
14
  assertion_error_ce = register_class_AssertionError(zend_ce_error);
298
299
14
  rounding_mode_ce = register_class_RoundingMode();
300
301
14
  BASIC_MINIT_SUBMODULE(var)
302
14
  BASIC_MINIT_SUBMODULE(file)
303
14
  BASIC_MINIT_SUBMODULE(browscap)
304
14
  BASIC_MINIT_SUBMODULE(standard_filters)
305
14
  BASIC_MINIT_SUBMODULE(user_filters)
306
14
  BASIC_MINIT_SUBMODULE(password)
307
14
  BASIC_MINIT_SUBMODULE(image)
308
309
#ifdef ZTS
310
  BASIC_MINIT_SUBMODULE(localeconv)
311
#endif
312
313
#ifdef ZEND_INTRIN_SSE4_2_FUNC_PTR
314
  BASIC_MINIT_SUBMODULE(string_intrin)
315
#endif
316
317
14
#ifdef ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_PTR
318
14
  BASIC_MINIT_SUBMODULE(crc32_x86_intrin)
319
14
#endif
320
321
#if defined(ZEND_INTRIN_AVX2_FUNC_PTR) || defined(ZEND_INTRIN_SSSE3_FUNC_PTR)
322
  BASIC_MINIT_SUBMODULE(base64_intrin)
323
#endif
324
325
14
  BASIC_MINIT_SUBMODULE(crypt)
326
327
14
  BASIC_MINIT_SUBMODULE(dir)
328
14
#ifdef HAVE_SYSLOG_H
329
14
  BASIC_MINIT_SUBMODULE(syslog)
330
14
#endif
331
14
  BASIC_MINIT_SUBMODULE(array)
332
14
  BASIC_MINIT_SUBMODULE(assert)
333
14
  BASIC_MINIT_SUBMODULE(url_scanner_ex)
334
14
#ifdef PHP_CAN_SUPPORT_PROC_OPEN
335
14
  BASIC_MINIT_SUBMODULE(proc_open)
336
14
#endif
337
14
  BASIC_MINIT_SUBMODULE(exec)
338
339
14
  BASIC_MINIT_SUBMODULE(user_streams)
340
341
14
  php_register_url_stream_wrapper("php", &php_stream_php_wrapper);
342
14
  php_register_url_stream_wrapper("file", &php_plain_files_wrapper);
343
14
  php_register_url_stream_wrapper("glob", &php_glob_stream_wrapper);
344
14
  php_register_url_stream_wrapper("data", &php_stream_rfc2397_wrapper);
345
14
  php_register_url_stream_wrapper("http", &php_stream_http_wrapper);
346
14
  php_register_url_stream_wrapper("ftp", &php_stream_ftp_wrapper);
347
348
14
  return SUCCESS;
349
14
}
350
/* }}} */
351
352
PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */
353
0
{
354
#ifdef ZTS
355
  ts_free_id(basic_globals_id);
356
#ifdef PHP_WIN32
357
  ts_free_id(php_win32_core_globals_id);
358
#endif
359
#else
360
0
  basic_globals_dtor(&basic_globals);
361
#ifdef PHP_WIN32
362
  php_win32_core_globals_dtor(&the_php_win32_core_globals);
363
#endif
364
0
#endif
365
366
0
  php_unregister_url_stream_wrapper("php");
367
0
  php_unregister_url_stream_wrapper("http");
368
0
  php_unregister_url_stream_wrapper("ftp");
369
370
0
  BASIC_MSHUTDOWN_SUBMODULE(browscap)
371
0
  BASIC_MSHUTDOWN_SUBMODULE(array)
372
0
  BASIC_MSHUTDOWN_SUBMODULE(assert)
373
0
  BASIC_MSHUTDOWN_SUBMODULE(url_scanner_ex)
374
0
  BASIC_MSHUTDOWN_SUBMODULE(file)
375
0
  BASIC_MSHUTDOWN_SUBMODULE(standard_filters)
376
#ifdef ZTS
377
  BASIC_MSHUTDOWN_SUBMODULE(localeconv)
378
#endif
379
0
  BASIC_MSHUTDOWN_SUBMODULE(crypt)
380
0
  BASIC_MSHUTDOWN_SUBMODULE(password)
381
0
  BASIC_MSHUTDOWN_SUBMODULE(image)
382
383
0
  return SUCCESS;
384
0
}
385
/* }}} */
386
387
PHP_RINIT_FUNCTION(basic) /* {{{ */
388
222k
{
389
222k
  memset(BG(strtok_table), 0, 256);
390
391
222k
  BG(serialize_lock) = 0;
392
222k
  memset(&BG(serialize), 0, sizeof(BG(serialize)));
393
222k
  memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
394
395
222k
  BG(strtok_string) = NULL;
396
222k
  BG(strtok_last) = NULL;
397
222k
  BG(ctype_string) = NULL;
398
222k
  BG(locale_changed) = 0;
399
222k
  BG(user_compare_fci) = empty_fcall_info;
400
222k
  BG(user_compare_fci_cache) = empty_fcall_info_cache;
401
222k
  BG(page_uid) = -1;
402
222k
  BG(page_gid) = -1;
403
222k
  BG(page_inode) = -1;
404
222k
  BG(page_mtime) = -1;
405
222k
#ifdef HAVE_PUTENV
406
222k
  zend_hash_init(&BG(putenv_ht), 1, NULL, php_putenv_destructor, 0);
407
222k
#endif
408
222k
  BG(user_shutdown_function_names) = NULL;
409
410
222k
  PHP_RINIT(filestat)(INIT_FUNC_ARGS_PASSTHRU);
411
222k
  BASIC_RINIT_SUBMODULE(dir)
412
222k
  BASIC_RINIT_SUBMODULE(url_scanner_ex)
413
414
  /* Initialize memory for last http headers */
415
222k
  ZVAL_UNDEF(&BG(last_http_headers));
416
417
  /* Setup default context */
418
222k
  FG(default_context) = NULL;
419
420
  /* Default to global wrappers only */
421
222k
  FG(stream_wrappers) = NULL;
422
423
  /* Default to global filters only */
424
222k
  FG(stream_filters) = NULL;
425
426
222k
  return SUCCESS;
427
222k
}
428
/* }}} */
429
430
PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
431
222k
{
432
222k
  if (BG(strtok_string)) {
433
10
    zend_string_release(BG(strtok_string));
434
10
    BG(strtok_string) = NULL;
435
10
  }
436
222k
#ifdef HAVE_PUTENV
437
222k
  tsrm_env_lock();
438
222k
  zend_hash_destroy(&BG(putenv_ht));
439
222k
  tsrm_env_unlock();
440
222k
#endif
441
442
222k
  if (BG(umask) != -1) {
443
0
    umask(BG(umask));
444
0
  }
445
446
  /* Check if locale was changed and change it back
447
   * to the value in startup environment */
448
222k
  if (BG(locale_changed)) {
449
0
    setlocale(LC_ALL, "C");
450
0
    zend_reset_lc_ctype_locale();
451
0
    zend_update_current_locale();
452
0
    if (BG(ctype_string)) {
453
0
      zend_string_release_ex(BG(ctype_string), 0);
454
0
      BG(ctype_string) = NULL;
455
0
    }
456
0
  }
457
458
  /* FG(stream_wrappers) and FG(stream_filters) are destroyed
459
   * during php_request_shutdown() */
460
461
222k
  PHP_RSHUTDOWN(filestat)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
462
222k
#ifdef HAVE_SYSLOG_H
463
222k
  BASIC_RSHUTDOWN_SUBMODULE(syslog);
464
222k
#endif
465
222k
  BASIC_RSHUTDOWN_SUBMODULE(assert)
466
222k
  BASIC_RSHUTDOWN_SUBMODULE(url_scanner_ex)
467
222k
  BASIC_RSHUTDOWN_SUBMODULE(streams)
468
#ifdef PHP_WIN32
469
  BASIC_RSHUTDOWN_SUBMODULE(win32_core_globals)
470
#endif
471
472
222k
  if (BG(user_tick_functions)) {
473
8
    zend_llist_destroy(BG(user_tick_functions));
474
8
    efree(BG(user_tick_functions));
475
8
    BG(user_tick_functions) = NULL;
476
8
  }
477
478
222k
  BASIC_RSHUTDOWN_SUBMODULE(user_filters)
479
222k
  BASIC_RSHUTDOWN_SUBMODULE(browscap)
480
481
  /* Free last http headers */
482
222k
  zval_ptr_dtor(&BG(last_http_headers));
483
484
222k
  BG(page_uid) = -1;
485
222k
  BG(page_gid) = -1;
486
222k
  return SUCCESS;
487
222k
}
488
/* }}} */
489
490
PHP_MINFO_FUNCTION(basic) /* {{{ */
491
1
{
492
1
  php_info_print_table_start();
493
1
  BASIC_MINFO_SUBMODULE(dl)
494
1
  BASIC_MINFO_SUBMODULE(mail)
495
1
  php_info_print_table_end();
496
1
  BASIC_MINFO_SUBMODULE(assert)
497
1
}
498
/* }}} */
499
500
/* {{{ Given the name of a constant this function will return the constant's associated value */
501
PHP_FUNCTION(constant)
502
9
{
503
9
  zend_string *const_name;
504
9
  zval *c;
505
9
  zend_class_entry *scope;
506
507
27
  ZEND_PARSE_PARAMETERS_START(1, 1)
508
36
    Z_PARAM_STR(const_name)
509
9
  ZEND_PARSE_PARAMETERS_END();
510
511
9
  scope = zend_get_executed_scope();
512
9
  c = zend_get_constant_ex(const_name, scope, ZEND_FETCH_CLASS_EXCEPTION);
513
9
  if (!c) {
514
3
    RETURN_THROWS();
515
3
  }
516
517
6
  ZVAL_COPY_OR_DUP(return_value, c);
518
6
  if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
519
0
    if (UNEXPECTED(zval_update_constant_ex(return_value, scope) != SUCCESS)) {
520
0
      RETURN_THROWS();
521
0
    }
522
0
  }
523
6
}
524
/* }}} */
525
526
/* {{{ Converts a packed inet address to a human readable IP address string */
527
PHP_FUNCTION(inet_ntop)
528
0
{
529
0
  char *address;
530
0
  size_t address_len;
531
0
  int af = AF_INET;
532
0
  char buffer[40];
533
534
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
535
0
    Z_PARAM_STRING(address, address_len)
536
0
  ZEND_PARSE_PARAMETERS_END();
537
538
0
#ifdef HAVE_IPV6
539
0
  if (address_len == 16) {
540
0
    af = AF_INET6;
541
0
  } else
542
0
#endif
543
0
  if (address_len != 4) {
544
0
    RETURN_FALSE;
545
0
  }
546
547
0
  if (!inet_ntop(af, address, buffer, sizeof(buffer))) {
548
0
    RETURN_FALSE;
549
0
  }
550
551
0
  RETURN_STRING(buffer);
552
0
}
553
/* }}} */
554
555
/* {{{ Converts a human readable IP address to a packed binary string */
556
PHP_FUNCTION(inet_pton)
557
0
{
558
0
  int ret, af = AF_INET;
559
0
  char *address;
560
0
  size_t address_len;
561
0
  char buffer[17];
562
563
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
564
0
    Z_PARAM_PATH(address, address_len)
565
0
  ZEND_PARSE_PARAMETERS_END();
566
567
0
  memset(buffer, 0, sizeof(buffer));
568
569
0
#ifdef HAVE_IPV6
570
0
  if (strchr(address, ':')) {
571
0
    af = AF_INET6;
572
0
  } else
573
0
#endif
574
0
  if (!strchr(address, '.')) {
575
0
    RETURN_FALSE;
576
0
  }
577
578
0
  ret = inet_pton(af, address, buffer);
579
580
0
  if (ret <= 0) {
581
0
    RETURN_FALSE;
582
0
  }
583
584
0
  RETURN_STRINGL(buffer, af == AF_INET ? 4 : 16);
585
0
}
586
/* }}} */
587
588
/* {{{ Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address */
589
PHP_FUNCTION(ip2long)
590
0
{
591
0
  char *addr;
592
0
  size_t addr_len;
593
0
  struct in_addr ip;
594
595
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
596
0
    Z_PARAM_PATH(addr, addr_len)
597
0
  ZEND_PARSE_PARAMETERS_END();
598
599
0
  if (addr_len == 0 || inet_pton(AF_INET, addr, &ip) != 1) {
600
0
    RETURN_FALSE;
601
0
  }
602
0
  RETURN_LONG(ntohl(ip.s_addr));
603
0
}
604
/* }}} */
605
606
/* {{{ Converts an (IPv4) Internet network address into a string in Internet standard dotted format */
607
PHP_FUNCTION(long2ip)
608
0
{
609
0
  zend_ulong ip;
610
0
  zend_long sip;
611
0
  struct in_addr myaddr;
612
0
  char str[40];
613
614
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
615
0
    Z_PARAM_LONG(sip)
616
0
  ZEND_PARSE_PARAMETERS_END();
617
618
  /* autoboxes on 32bit platforms, but that's expected */
619
0
  ip = (zend_ulong)sip;
620
621
0
  myaddr.s_addr = htonl(ip);
622
0
  const char* result = inet_ntop(AF_INET, &myaddr, str, sizeof(str));
623
0
  ZEND_ASSERT(result != NULL);
624
625
0
  RETURN_STRING(str);
626
0
}
627
/* }}} */
628
629
/********************
630
 * System Functions *
631
 ********************/
632
633
1
PHPAPI zend_string *php_getenv(const char *str, size_t str_len) {
634
#ifdef PHP_WIN32
635
  {
636
    wchar_t *keyw = php_win32_cp_conv_any_to_w(str, str_len, PHP_WIN32_CP_IGNORE_LEN_P);
637
    if (!keyw) {
638
      return NULL;
639
    }
640
641
    SetLastError(0);
642
    /* If the given buffer is not large enough to hold the data, the return value is
643
     * the buffer size,  in characters, required to hold the string and its terminating
644
     * null character. We use this return value to alloc the final buffer. */
645
    wchar_t dummybuf;
646
    DWORD size = GetEnvironmentVariableW(keyw, &dummybuf, 0);
647
    if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
648
      /* The environment variable doesn't exist. */
649
      free(keyw);
650
      return NULL;
651
    }
652
653
    if (size == 0) {
654
      /* env exists, but it is empty */
655
      free(keyw);
656
      return ZSTR_EMPTY_ALLOC();
657
    }
658
659
    wchar_t *valw = emalloc((size + 1) * sizeof(wchar_t));
660
    size = GetEnvironmentVariableW(keyw, valw, size);
661
    if (size == 0) {
662
      /* has been removed between the two calls */
663
      free(keyw);
664
      efree(valw);
665
      return ZSTR_EMPTY_ALLOC();
666
    } else {
667
      char *ptr = php_win32_cp_w_to_any(valw);
668
      zend_string *result = zend_string_init(ptr, strlen(ptr), 0);
669
      free(ptr);
670
      free(keyw);
671
      efree(valw);
672
      return result;
673
    }
674
  }
675
#else
676
1
  tsrm_env_lock();
677
678
  /* system method returns a const */
679
1
  char *ptr = getenv(str);
680
1
  zend_string *result = NULL;
681
1
  if (ptr) {
682
0
    result = zend_string_init(ptr, strlen(ptr), 0);
683
0
  }
684
685
1
  tsrm_env_unlock();
686
1
  return result;
687
1
#endif
688
1
}
689
690
/* {{{ Get the value of an environment variable or every available environment variable
691
   if no varname is present  */
692
PHP_FUNCTION(getenv)
693
1
{
694
1
  char *str = NULL;
695
1
  size_t str_len;
696
1
  bool local_only = 0;
697
698
3
  ZEND_PARSE_PARAMETERS_START(0, 2)
699
3
    Z_PARAM_OPTIONAL
700
4
    Z_PARAM_STRING_OR_NULL(str, str_len)
701
3
    Z_PARAM_BOOL(local_only)
702
1
  ZEND_PARSE_PARAMETERS_END();
703
704
1
  if (!str) {
705
0
    array_init(return_value);
706
0
    php_load_environment_variables(return_value);
707
0
    return;
708
0
  }
709
710
1
  if (!local_only) {
711
    /* SAPI method returns an emalloc()'d string */
712
1
    char *ptr = sapi_getenv(str, str_len);
713
1
    if (ptr) {
714
      // TODO: avoid reallocation ???
715
0
      RETVAL_STRING(ptr);
716
0
      efree(ptr);
717
0
      return;
718
0
    }
719
1
  }
720
721
1
  zend_string *res = php_getenv(str, str_len);
722
1
  if (res) {
723
0
    RETURN_STR(res);
724
0
  }
725
1
  RETURN_FALSE;
726
1
}
727
/* }}} */
728
729
#ifdef HAVE_PUTENV
730
/* {{{ Set the value of an environment variable */
731
PHP_FUNCTION(putenv)
732
0
{
733
0
  char *setting;
734
0
  size_t setting_len;
735
0
  char *p, **env;
736
0
  putenv_entry pe;
737
#ifdef PHP_WIN32
738
  const char *value = NULL;
739
  int error_code;
740
#endif
741
742
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
743
0
    Z_PARAM_STRING(setting, setting_len)
744
0
  ZEND_PARSE_PARAMETERS_END();
745
746
0
  if (setting_len == 0 || setting[0] == '=') {
747
0
    zend_argument_value_error(1, "must have a valid syntax");
748
0
    RETURN_THROWS();
749
0
  }
750
751
0
  pe.putenv_string = zend_strndup(setting, setting_len);
752
0
  if ((p = strchr(setting, '='))) {
753
0
    pe.key = zend_string_init(setting, p - setting, 0);
754
#ifdef PHP_WIN32
755
    value = p + 1;
756
#endif
757
0
  } else {
758
0
    pe.key = zend_string_init(setting, setting_len, 0);
759
0
  }
760
761
0
  tsrm_env_lock();
762
0
  zend_hash_del(&BG(putenv_ht), pe.key);
763
764
  /* find previous value */
765
0
  pe.previous_value = NULL;
766
0
  for (env = environ; env != NULL && *env != NULL; env++) {
767
0
    if (!strncmp(*env, ZSTR_VAL(pe.key), ZSTR_LEN(pe.key))
768
0
        && (*env)[ZSTR_LEN(pe.key)] == '=') { /* found it */
769
#ifdef PHP_WIN32
770
      /* must copy previous value because MSVCRT's putenv can free the string without notice */
771
      pe.previous_value = estrdup(*env);
772
#else
773
0
      pe.previous_value = *env;
774
0
#endif
775
0
      break;
776
0
    }
777
0
  }
778
779
0
#ifdef HAVE_UNSETENV
780
0
  if (!p) { /* no '=' means we want to unset it */
781
0
    unsetenv(pe.putenv_string);
782
0
  }
783
0
  if (!p || putenv(pe.putenv_string) == 0) { /* success */
784
#else
785
# ifndef PHP_WIN32
786
  if (putenv(pe.putenv_string) == 0) { /* success */
787
# else
788
    wchar_t *keyw, *valw = NULL;
789
790
    keyw = php_win32_cp_any_to_w(ZSTR_VAL(pe.key));
791
    if (value) {
792
      valw = php_win32_cp_any_to_w(value);
793
    }
794
    /* valw may be NULL, but the failed conversion still needs to be checked. */
795
    if (!keyw || (!valw && value)) {
796
      tsrm_env_unlock();
797
      free(pe.putenv_string);
798
      zend_string_release(pe.key);
799
      free(keyw);
800
      free(valw);
801
      RETURN_FALSE;
802
    }
803
804
  error_code = SetEnvironmentVariableW(keyw, valw);
805
806
  if (error_code != 0
807
# ifndef ZTS
808
  /* We need both SetEnvironmentVariable and _putenv here as some
809
    dependency lib could use either way to read the environment.
810
    Obviously the CRT version will be useful more often. But
811
    generally, doing both brings us on the safe track at least
812
    in NTS build. */
813
  && _wputenv_s(keyw, valw ? valw : L"") == 0
814
# endif
815
  ) { /* success */
816
# endif
817
#endif
818
0
    zend_hash_add_mem(&BG(putenv_ht), pe.key, &pe, sizeof(putenv_entry));
819
0
#ifdef HAVE_TZSET
820
0
    if (zend_string_equals_literal_ci(pe.key, "TZ")) {
821
0
      tzset();
822
0
    }
823
0
#endif
824
0
    tsrm_env_unlock();
825
#ifdef PHP_WIN32
826
    free(keyw);
827
    free(valw);
828
#endif
829
0
    RETURN_TRUE;
830
0
  } else {
831
0
    tsrm_env_unlock();
832
0
    free(pe.putenv_string);
833
0
    zend_string_release(pe.key);
834
#ifdef PHP_WIN32
835
    free(keyw);
836
    free(valw);
837
#endif
838
0
    RETURN_FALSE;
839
0
  }
840
0
}
841
/* }}} */
842
#endif
843
844
/* {{{ free_argv()
845
   Free the memory allocated to an argv array. */
846
static void free_argv(char **argv, int argc)
847
0
{
848
0
  int i;
849
850
0
  if (argv) {
851
0
    for (i = 0; i < argc; i++) {
852
0
      if (argv[i]) {
853
0
        efree(argv[i]);
854
0
      }
855
0
    }
856
0
    efree(argv);
857
0
  }
858
0
}
859
/* }}} */
860
861
/* {{{ free_longopts()
862
   Free the memory allocated to an longopt array. */
863
static void free_longopts(opt_struct *longopts)
864
0
{
865
0
  opt_struct *p;
866
867
0
  if (longopts) {
868
0
    for (p = longopts; p && p->opt_char != '-'; p++) {
869
0
      if (p->opt_name != NULL) {
870
0
        efree((char *)(p->opt_name));
871
0
      }
872
0
    }
873
0
  }
874
0
}
875
/* }}} */
876
877
/* {{{ parse_opts()
878
   Convert the typical getopt input characters to the php_getopt struct array */
879
static int parse_opts(char * opts, opt_struct ** result)
880
0
{
881
0
  opt_struct * paras = NULL;
882
0
  unsigned int i, count = 0;
883
0
  unsigned int opts_len = (unsigned int)strlen(opts);
884
885
0
  for (i = 0; i < opts_len; i++) {
886
0
    if ((opts[i] >= 48 && opts[i] <= 57) ||
887
0
      (opts[i] >= 65 && opts[i] <= 90) ||
888
0
      (opts[i] >= 97 && opts[i] <= 122)
889
0
    ) {
890
0
      count++;
891
0
    }
892
0
  }
893
894
0
  paras = safe_emalloc(sizeof(opt_struct), count, 0);
895
0
  memset(paras, 0, sizeof(opt_struct) * count);
896
0
  *result = paras;
897
0
  while ( (*opts >= 48 && *opts <= 57) || /* 0 - 9 */
898
0
      (*opts >= 65 && *opts <= 90) || /* A - Z */
899
0
      (*opts >= 97 && *opts <= 122)   /* a - z */
900
0
  ) {
901
0
    paras->opt_char = *opts;
902
0
    paras->need_param = *(++opts) == ':';
903
0
    paras->opt_name = NULL;
904
0
    if (paras->need_param == 1) {
905
0
      opts++;
906
0
      if (*opts == ':') {
907
0
        paras->need_param++;
908
0
        opts++;
909
0
      }
910
0
    }
911
0
    paras++;
912
0
  }
913
0
  return count;
914
0
}
915
/* }}} */
916
917
/* {{{ Get options from the command line argument list */
918
PHP_FUNCTION(getopt)
919
0
{
920
0
  char *options = NULL, **argv = NULL;
921
0
  char opt[2] = { '\0' };
922
0
  char *optname;
923
0
  int argc = 0, o;
924
0
  size_t options_len = 0, len;
925
0
  char *php_optarg = NULL;
926
0
  int php_optind = 1;
927
0
  zval val, *args = NULL, *p_longopts = NULL;
928
0
  zval *zoptind = NULL;
929
0
  size_t optname_len = 0;
930
0
  opt_struct *opts, *orig_opts;
931
932
0
  ZEND_PARSE_PARAMETERS_START(1, 3)
933
0
    Z_PARAM_STRING(options, options_len)
934
0
    Z_PARAM_OPTIONAL
935
0
    Z_PARAM_ARRAY(p_longopts)
936
0
    Z_PARAM_ZVAL(zoptind)
937
0
  ZEND_PARSE_PARAMETERS_END();
938
939
  /* Init zoptind to 1 */
940
0
  if (zoptind) {
941
0
    ZEND_TRY_ASSIGN_REF_LONG(zoptind, 1);
942
0
  }
943
944
  /* Get argv from the global symbol table. We calculate argc ourselves
945
   * in order to be on the safe side, even though it is also available
946
   * from the symbol table. */
947
0
  if ((Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY || zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER))) &&
948
0
    ((args = zend_hash_find_ex_ind(Z_ARRVAL_P(&PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL ||
949
0
    (args = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL)
950
0
  ) {
951
0
    int pos = 0;
952
0
    zval *entry;
953
954
0
    if (Z_TYPE_P(args) != IS_ARRAY) {
955
0
      RETURN_FALSE;
956
0
    }
957
0
    argc = zend_hash_num_elements(Z_ARRVAL_P(args));
958
959
    /* Attempt to allocate enough memory to hold all of the arguments
960
     * and a trailing NULL */
961
0
    argv = (char **) safe_emalloc(sizeof(char *), (argc + 1), 0);
962
963
    /* Iterate over the hash to construct the argv array. */
964
0
    ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), entry) {
965
0
      zend_string *tmp_arg_str;
966
0
      zend_string *arg_str = zval_get_tmp_string(entry, &tmp_arg_str);
967
968
0
      argv[pos++] = estrdup(ZSTR_VAL(arg_str));
969
970
0
      zend_tmp_string_release(tmp_arg_str);
971
0
    } ZEND_HASH_FOREACH_END();
972
973
    /* The C Standard requires argv[argc] to be NULL - this might
974
     * keep some getopt implementations happy. */
975
0
    argv[argc] = NULL;
976
0
  } else {
977
    /* Return false if we can't find argv. */
978
0
    RETURN_FALSE;
979
0
  }
980
981
0
  len = parse_opts(options, &opts);
982
983
0
  if (p_longopts) {
984
0
    int count;
985
0
    zval *entry;
986
987
0
    count = zend_hash_num_elements(Z_ARRVAL_P(p_longopts));
988
989
    /* the first <len> slots are filled by the one short ops
990
     * we now extend our array and jump to the new added structs */
991
0
    opts = (opt_struct *) safe_erealloc(opts, sizeof(opt_struct), (len + count + 1), 0);
992
0
    orig_opts = opts;
993
0
    opts += len;
994
995
0
    memset(opts, 0, count * sizeof(opt_struct));
996
997
    /* Iterate over the hash to construct the argv array. */
998
0
    ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(p_longopts), entry) {
999
0
      zend_string *tmp_arg_str;
1000
0
      zend_string *arg_str = zval_get_tmp_string(entry, &tmp_arg_str);
1001
1002
0
      opts->need_param = 0;
1003
0
      opts->opt_name = estrdup(ZSTR_VAL(arg_str));
1004
0
      len = strlen(opts->opt_name);
1005
0
      if ((len > 0) && (opts->opt_name[len - 1] == ':')) {
1006
0
        opts->need_param++;
1007
0
        opts->opt_name[len - 1] = '\0';
1008
0
        if ((len > 1) && (opts->opt_name[len - 2] == ':')) {
1009
0
          opts->need_param++;
1010
0
          opts->opt_name[len - 2] = '\0';
1011
0
        }
1012
0
      }
1013
0
      opts->opt_char = 0;
1014
0
      opts++;
1015
1016
0
      zend_tmp_string_release(tmp_arg_str);
1017
0
    } ZEND_HASH_FOREACH_END();
1018
0
  } else {
1019
0
    opts = (opt_struct*) erealloc(opts, sizeof(opt_struct) * (len + 1));
1020
0
    orig_opts = opts;
1021
0
    opts += len;
1022
0
  }
1023
1024
  /* php_getopt want to identify the last param */
1025
0
  opts->opt_char   = '-';
1026
0
  opts->need_param = 0;
1027
0
  opts->opt_name   = NULL;
1028
1029
  /* Initialize the return value as an array. */
1030
0
  array_init(return_value);
1031
1032
  /* after our pointer arithmetic jump back to the first element */
1033
0
  opts = orig_opts;
1034
1035
0
  while ((o = php_getopt(argc, argv, opts, &php_optarg, &php_optind, 0, 1)) != -1) {
1036
    /* Skip unknown arguments. */
1037
0
    if (o == PHP_GETOPT_INVALID_ARG) {
1038
0
      continue;
1039
0
    }
1040
1041
    /* Prepare the option character and the argument string. */
1042
0
    if (o == 0) {
1043
0
      optname = opts[php_optidx].opt_name;
1044
0
    } else {
1045
0
      if (o == 1) {
1046
0
        o = '-';
1047
0
      }
1048
0
      opt[0] = o;
1049
0
      optname = opt;
1050
0
    }
1051
1052
0
    if (php_optarg != NULL) {
1053
      /* keep the arg as binary, since the encoding is not known */
1054
0
      ZVAL_STRING(&val, php_optarg);
1055
0
    } else {
1056
0
      ZVAL_FALSE(&val);
1057
0
    }
1058
1059
    /* Add this option / argument pair to the result hash. */
1060
0
    optname_len = strlen(optname);
1061
0
    zend_long opt_name_as_long = 0;
1062
0
    if (!(optname_len > 1 && optname[0] == '0') && is_numeric_string(optname, optname_len, &opt_name_as_long, NULL, 0) == IS_LONG) {
1063
      /* numeric string */
1064
0
      if ((args = zend_hash_index_find(Z_ARRVAL_P(return_value), opt_name_as_long)) != NULL) {
1065
0
        if (Z_TYPE_P(args) != IS_ARRAY) {
1066
0
          convert_to_array(args);
1067
0
        }
1068
0
        zend_hash_next_index_insert(Z_ARRVAL_P(args), &val);
1069
0
      } else {
1070
0
        zend_hash_index_update(Z_ARRVAL_P(return_value), opt_name_as_long, &val);
1071
0
      }
1072
0
    } else {
1073
      /* other strings */
1074
0
      if ((args = zend_hash_str_find(Z_ARRVAL_P(return_value), optname, optname_len)) != NULL) {
1075
0
        if (Z_TYPE_P(args) != IS_ARRAY) {
1076
0
          convert_to_array(args);
1077
0
        }
1078
0
        zend_hash_next_index_insert(Z_ARRVAL_P(args), &val);
1079
0
      } else {
1080
0
        zend_hash_str_add(Z_ARRVAL_P(return_value), optname, optname_len, &val);
1081
0
      }
1082
0
    }
1083
1084
0
    php_optarg = NULL;
1085
0
  }
1086
1087
  /* Set zoptind to php_optind */
1088
0
  if (zoptind) {
1089
0
    ZEND_TRY_ASSIGN_REF_LONG(zoptind, php_optind);
1090
0
  }
1091
1092
0
  free_longopts(orig_opts);
1093
0
  efree(orig_opts);
1094
0
  free_argv(argv, argc);
1095
0
}
1096
/* }}} */
1097
1098
/* {{{ Flush the output buffer */
1099
PHP_FUNCTION(flush)
1100
0
{
1101
0
  ZEND_PARSE_PARAMETERS_NONE();
1102
1103
0
  sapi_flush();
1104
0
}
1105
/* }}} */
1106
1107
/* {{{ Delay for a given number of seconds */
1108
PHP_FUNCTION(sleep)
1109
0
{
1110
0
  zend_long num;
1111
1112
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1113
0
    Z_PARAM_LONG(num)
1114
0
  ZEND_PARSE_PARAMETERS_END();
1115
1116
0
  if (num < 0) {
1117
0
    zend_argument_value_error(1, "must be greater than or equal to 0");
1118
0
    RETURN_THROWS();
1119
0
  }
1120
1121
0
  RETURN_LONG(php_sleep((unsigned int)num));
1122
0
}
1123
/* }}} */
1124
1125
/* {{{ Delay for a given number of micro seconds */
1126
PHP_FUNCTION(usleep)
1127
0
{
1128
0
  zend_long num;
1129
1130
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1131
0
    Z_PARAM_LONG(num)
1132
0
  ZEND_PARSE_PARAMETERS_END();
1133
1134
0
  if (num < 0) {
1135
0
    zend_argument_value_error(1, "must be greater than or equal to 0");
1136
0
    RETURN_THROWS();
1137
0
  }
1138
1139
0
#ifdef HAVE_USLEEP
1140
0
  usleep((unsigned int)num);
1141
0
#endif
1142
0
}
1143
/* }}} */
1144
1145
#ifdef HAVE_NANOSLEEP
1146
/* {{{ Delay for a number of seconds and nano seconds */
1147
PHP_FUNCTION(time_nanosleep)
1148
0
{
1149
0
  zend_long tv_sec, tv_nsec;
1150
0
  struct timespec php_req, php_rem;
1151
1152
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
1153
0
    Z_PARAM_LONG(tv_sec)
1154
0
    Z_PARAM_LONG(tv_nsec)
1155
0
  ZEND_PARSE_PARAMETERS_END();
1156
1157
0
  if (tv_sec < 0) {
1158
0
    zend_argument_value_error(1, "must be greater than or equal to 0");
1159
0
    RETURN_THROWS();
1160
0
  }
1161
0
  if (tv_nsec < 0) {
1162
0
    zend_argument_value_error(2, "must be greater than or equal to 0");
1163
0
    RETURN_THROWS();
1164
0
  }
1165
1166
0
  php_req.tv_sec = (time_t) tv_sec;
1167
0
  php_req.tv_nsec = (long)tv_nsec;
1168
0
  if (!nanosleep(&php_req, &php_rem)) {
1169
0
    RETURN_TRUE;
1170
0
  } else if (errno == EINTR) {
1171
0
    array_init(return_value);
1172
0
    MSAN_UNPOISON(php_rem);
1173
0
    add_assoc_long_ex(return_value, "seconds", sizeof("seconds")-1, php_rem.tv_sec);
1174
0
    add_assoc_long_ex(return_value, "nanoseconds", sizeof("nanoseconds")-1, php_rem.tv_nsec);
1175
0
    return;
1176
0
  } else if (errno == EINVAL) {
1177
0
    zend_value_error("Nanoseconds was not in the range 0 to 999 999 999 or seconds was negative");
1178
0
    RETURN_THROWS();
1179
0
  }
1180
1181
0
  RETURN_FALSE;
1182
0
}
1183
/* }}} */
1184
1185
/* {{{ Make the script sleep until the specified time */
1186
PHP_FUNCTION(time_sleep_until)
1187
0
{
1188
0
  double target_secs;
1189
0
  struct timeval tm;
1190
0
  struct timespec php_req, php_rem;
1191
0
  uint64_t current_ns, target_ns, diff_ns;
1192
0
  const uint64_t ns_per_sec = 1000000000;
1193
0
  const double top_target_sec = (double)(UINT64_MAX / ns_per_sec);
1194
1195
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1196
0
    Z_PARAM_DOUBLE(target_secs)
1197
0
  ZEND_PARSE_PARAMETERS_END();
1198
1199
0
  if (gettimeofday((struct timeval *) &tm, NULL) != 0) {
1200
0
    RETURN_FALSE;
1201
0
  }
1202
1203
0
  if (UNEXPECTED(!(target_secs >= 0 && target_secs <= top_target_sec))) {
1204
0
    zend_argument_value_error(1, "must be between 0 and %" PRIu64, (uint64_t)top_target_sec);
1205
0
    RETURN_THROWS();
1206
0
  }
1207
1208
0
  target_ns = (uint64_t) (target_secs * ns_per_sec);
1209
0
  current_ns = ((uint64_t) tm.tv_sec) * ns_per_sec + ((uint64_t) tm.tv_usec) * 1000;
1210
0
  if (target_ns < current_ns) {
1211
0
    php_error_docref(NULL, E_WARNING, "Argument #1 ($timestamp) must be greater than or equal to the current time");
1212
0
    RETURN_FALSE;
1213
0
  }
1214
1215
0
  diff_ns = target_ns - current_ns;
1216
0
  php_req.tv_sec = (time_t) (diff_ns / ns_per_sec);
1217
0
  php_req.tv_nsec = (long) (diff_ns % ns_per_sec);
1218
1219
0
  while (nanosleep(&php_req, &php_rem)) {
1220
0
    if (errno == EINTR) {
1221
0
      php_req.tv_sec = php_rem.tv_sec;
1222
0
      php_req.tv_nsec = php_rem.tv_nsec;
1223
0
    } else {
1224
0
      RETURN_FALSE;
1225
0
    }
1226
0
  }
1227
1228
0
  RETURN_TRUE;
1229
0
}
1230
/* }}} */
1231
#endif
1232
1233
/* {{{ Get the name of the owner of the current PHP script */
1234
PHP_FUNCTION(get_current_user)
1235
0
{
1236
0
  ZEND_PARSE_PARAMETERS_NONE();
1237
1238
0
  RETURN_STRING(php_get_current_user());
1239
0
}
1240
/* }}} */
1241
1242
80
#define ZVAL_SET_INI_STR(zv, val) do { \
1243
80
  if (ZSTR_IS_INTERNED(val)) { \
1244
71
    ZVAL_INTERNED_STR(zv, val); \
1245
71
  } else if (ZSTR_LEN(val) == 0) { \
1246
0
    ZVAL_EMPTY_STRING(zv); \
1247
9
  } else if (ZSTR_LEN(val) == 1) { \
1248
2
    ZVAL_CHAR(zv, ZSTR_VAL(val)[0]); \
1249
7
  } else if (!(GC_FLAGS(val) & GC_PERSISTENT)) { \
1250
7
    ZVAL_NEW_STR(zv, zend_string_copy(val)); \
1251
7
  } else { \
1252
0
    ZVAL_NEW_STR(zv, zend_string_init(ZSTR_VAL(val), ZSTR_LEN(val), 0)); \
1253
0
  } \
1254
80
} while (0)
1255
1256
static void add_config_entries(HashTable *hash, zval *return_value);
1257
1258
/* {{{ add_config_entry */
1259
static void add_config_entry(zend_ulong h, zend_string *key, zval *entry, zval *retval)
1260
0
{
1261
0
  if (Z_TYPE_P(entry) == IS_STRING) {
1262
0
    zval str_zv;
1263
0
    ZVAL_SET_INI_STR(&str_zv, Z_STR_P(entry));
1264
0
    if (key) {
1265
0
      add_assoc_zval_ex(retval, ZSTR_VAL(key), ZSTR_LEN(key), &str_zv);
1266
0
    } else {
1267
0
      add_index_zval(retval, h, &str_zv);
1268
0
    }
1269
0
  } else if (Z_TYPE_P(entry) == IS_ARRAY) {
1270
0
    zval tmp;
1271
0
    array_init(&tmp);
1272
0
    add_config_entries(Z_ARRVAL_P(entry), &tmp);
1273
0
    zend_hash_update(Z_ARRVAL_P(retval), key, &tmp);
1274
0
  }
1275
0
}
1276
/* }}} */
1277
1278
/* {{{ add_config_entries */
1279
static void add_config_entries(HashTable *hash, zval *return_value) /* {{{ */
1280
0
{
1281
0
  zend_ulong h;
1282
0
  zend_string *key;
1283
0
  zval *zv;
1284
1285
0
  ZEND_HASH_FOREACH_KEY_VAL(hash, h, key, zv)
1286
0
    add_config_entry(h, key, zv, return_value);
1287
0
  ZEND_HASH_FOREACH_END();
1288
0
}
1289
/* }}} */
1290
1291
/* {{{ Get the value of a PHP configuration option */
1292
PHP_FUNCTION(get_cfg_var)
1293
0
{
1294
0
  zend_string *varname;
1295
1296
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1297
0
    Z_PARAM_STR(varname)
1298
0
  ZEND_PARSE_PARAMETERS_END();
1299
1300
0
  zval *retval = cfg_get_entry_ex(varname);
1301
1302
0
  if (retval) {
1303
0
    if (Z_TYPE_P(retval) == IS_ARRAY) {
1304
0
      array_init(return_value);
1305
0
      add_config_entries(Z_ARRVAL_P(retval), return_value);
1306
0
      return;
1307
0
    } else {
1308
0
      ZVAL_SET_INI_STR(return_value, Z_STR_P(retval));
1309
0
    }
1310
0
  } else {
1311
0
    RETURN_FALSE;
1312
0
  }
1313
0
}
1314
/* }}} */
1315
1316
/*
1317
  1st arg = error message
1318
  2nd arg = error option
1319
  3rd arg = optional parameters (email address or tcp address)
1320
  4th arg = used for additional headers if email
1321
1322
error options:
1323
  0 = send to php_error_log (uses syslog or file depending on ini setting)
1324
  1 = send via email to 3rd parameter 4th option = additional headers
1325
  2 = no longer an option
1326
  3 = save to file in 3rd parameter
1327
  4 = send to SAPI logger directly
1328
*/
1329
1330
/* {{{ Send an error message somewhere */
1331
PHP_FUNCTION(error_log)
1332
2
{
1333
2
  zend_string *message, *opt = NULL, *headers = NULL;
1334
2
  zend_long erropt = 0;
1335
1336
6
  ZEND_PARSE_PARAMETERS_START(1, 4)
1337
8
    Z_PARAM_STR(message)
1338
2
    Z_PARAM_OPTIONAL
1339
4
    Z_PARAM_LONG(erropt)
1340
0
    Z_PARAM_PATH_STR_OR_NULL(opt)
1341
0
    Z_PARAM_STR_OR_NULL(headers)
1342
2
  ZEND_PARSE_PARAMETERS_END();
1343
1344
2
  RETURN_BOOL(_php_error_log((int) erropt, message, opt, headers) == SUCCESS);
1345
2
}
1346
/* }}} */
1347
1348
PHPAPI zend_result _php_error_log(int opt_err, const zend_string *message, const zend_string *opt, const zend_string *headers) /* {{{ */
1349
2
{
1350
2
  php_stream *stream = NULL;
1351
2
  size_t nbytes;
1352
1353
2
  switch (opt_err)
1354
2
  {
1355
0
    case 1:   /*send an email */
1356
0
      if (!php_mail(ZSTR_VAL(opt), "PHP error_log message", ZSTR_VAL(message), ZSTR_VAL(headers), NULL)) {
1357
0
        return FAILURE;
1358
0
      }
1359
0
      break;
1360
1361
0
    case 2:   /*send to an address */
1362
0
      zend_value_error("TCP/IP option is not available for error logging");
1363
0
      return FAILURE;
1364
1365
0
    case 3:   /*save to a file */
1366
0
      stream = php_stream_open_wrapper(ZSTR_VAL(opt), "a", REPORT_ERRORS, NULL);
1367
0
      if (!stream) {
1368
0
        return FAILURE;
1369
0
      }
1370
0
      nbytes = php_stream_write(stream, ZSTR_VAL(message), ZSTR_LEN(message));
1371
0
      php_stream_close(stream);
1372
0
      if (nbytes != ZSTR_LEN(message)) {
1373
0
        return FAILURE;
1374
0
      }
1375
0
      break;
1376
1377
0
    case 4: /* send to SAPI */
1378
0
      if (sapi_module.log_message) {
1379
0
        sapi_module.log_message(ZSTR_VAL(message), -1);
1380
0
      } else {
1381
0
        return FAILURE;
1382
0
      }
1383
0
      break;
1384
1385
2
    default:
1386
2
      php_log_err_with_severity(ZSTR_VAL(message), LOG_NOTICE);
1387
2
      break;
1388
2
  }
1389
2
  return SUCCESS;
1390
2
}
1391
/* }}} */
1392
1393
/* {{{ Get the last occurred error as associative array. Returns NULL if there hasn't been an error yet. */
1394
PHP_FUNCTION(error_get_last)
1395
33.5k
{
1396
33.5k
  ZEND_PARSE_PARAMETERS_NONE();
1397
1398
33.5k
  if (PG(last_error_message)) {
1399
33.4k
    zval tmp;
1400
33.4k
    array_init(return_value);
1401
1402
33.4k
    ZVAL_LONG(&tmp, PG(last_error_type));
1403
33.4k
    zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
1404
1405
33.4k
    ZVAL_STR_COPY(&tmp, PG(last_error_message));
1406
33.4k
    zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
1407
1408
33.4k
    ZVAL_STR_COPY(&tmp, PG(last_error_file));
1409
33.4k
    zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
1410
1411
33.4k
    ZVAL_LONG(&tmp, PG(last_error_lineno));
1412
33.4k
    zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
1413
1414
33.4k
    if (!Z_ISUNDEF(EG(last_fatal_error_backtrace))) {
1415
0
      ZVAL_COPY(&tmp, &EG(last_fatal_error_backtrace));
1416
0
      zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_TRACE), &tmp);
1417
0
    }
1418
33.4k
  }
1419
33.5k
}
1420
/* }}} */
1421
1422
/* {{{ Clear the last occurred error. */
1423
PHP_FUNCTION(error_clear_last)
1424
109
{
1425
109
  ZEND_PARSE_PARAMETERS_NONE();
1426
1427
109
  if (PG(last_error_message)) {
1428
7
    PG(last_error_type) = 0;
1429
7
    PG(last_error_lineno) = 0;
1430
1431
7
    zend_string_release(PG(last_error_message));
1432
7
    PG(last_error_message) = NULL;
1433
1434
7
    if (PG(last_error_file)) {
1435
7
      zend_string_release(PG(last_error_file));
1436
7
      PG(last_error_file) = NULL;
1437
7
    }
1438
7
  }
1439
1440
109
  zval_ptr_dtor(&EG(last_fatal_error_backtrace));
1441
109
  ZVAL_UNDEF(&EG(last_fatal_error_backtrace));
1442
109
}
1443
/* }}} */
1444
1445
/* {{{ Call a user function which is the first parameter
1446
   Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
1447
PHP_FUNCTION(call_user_func)
1448
71
{
1449
71
  zval retval;
1450
71
  zend_fcall_info fci;
1451
71
  zend_fcall_info_cache fci_cache;
1452
1453
213
  ZEND_PARSE_PARAMETERS_START(1, -1)
1454
284
    Z_PARAM_FUNC(fci, fci_cache)
1455
70
    Z_PARAM_VARIADIC_WITH_NAMED(fci.params, fci.param_count, fci.named_params)
1456
71
  ZEND_PARSE_PARAMETERS_END();
1457
1458
70
  fci.retval = &retval;
1459
1460
70
  if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1461
58
    if (Z_ISREF(retval)) {
1462
1
      zend_unwrap_reference(&retval);
1463
1
    }
1464
58
    ZVAL_COPY_VALUE(return_value, &retval);
1465
58
  }
1466
70
}
1467
/* }}} */
1468
1469
/* {{{ Call a user function which is the first parameter with the arguments contained in array
1470
   Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
1471
PHP_FUNCTION(call_user_func_array)
1472
20
{
1473
20
  zval retval;
1474
20
  HashTable *params;
1475
20
  zend_fcall_info fci;
1476
20
  zend_fcall_info_cache fci_cache;
1477
1478
59
  ZEND_PARSE_PARAMETERS_START(2, 2)
1479
76
    Z_PARAM_FUNC(fci, fci_cache)
1480
95
    Z_PARAM_ARRAY_HT(params)
1481
20
  ZEND_PARSE_PARAMETERS_END();
1482
1483
19
  fci.named_params = params;
1484
19
  fci.retval = &retval;
1485
1486
19
  if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1487
13
    if (Z_ISREF(retval)) {
1488
0
      zend_unwrap_reference(&retval);
1489
0
    }
1490
13
    ZVAL_COPY_VALUE(return_value, &retval);
1491
13
  }
1492
19
}
1493
/* }}} */
1494
1495
/* {{{ Call a user function which is the first parameter */
1496
PHP_FUNCTION(forward_static_call)
1497
0
{
1498
0
  zval retval;
1499
0
  zend_fcall_info fci;
1500
0
  zend_fcall_info_cache fci_cache;
1501
0
  zend_class_entry *called_scope;
1502
1503
0
  ZEND_PARSE_PARAMETERS_START(1, -1)
1504
0
    Z_PARAM_FUNC(fci, fci_cache)
1505
0
    Z_PARAM_VARIADIC('*', fci.params, fci.param_count)
1506
0
  ZEND_PARSE_PARAMETERS_END();
1507
1508
0
  if (!EX(prev_execute_data) || !EX(prev_execute_data)->func->common.scope) {
1509
0
    zend_throw_error(NULL, "Cannot call forward_static_call() when no class scope is active");
1510
0
    RETURN_THROWS();
1511
0
  }
1512
1513
0
  fci.retval = &retval;
1514
1515
0
  called_scope = zend_get_called_scope(execute_data);
1516
0
  if (called_scope && fci_cache.calling_scope &&
1517
0
    instanceof_function(called_scope, fci_cache.calling_scope)) {
1518
0
      fci_cache.called_scope = called_scope;
1519
0
  }
1520
1521
0
  if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1522
0
    if (Z_ISREF(retval)) {
1523
0
      zend_unwrap_reference(&retval);
1524
0
    }
1525
0
    ZVAL_COPY_VALUE(return_value, &retval);
1526
0
  }
1527
0
}
1528
/* }}} */
1529
1530
/* {{{ Call a static method which is the first parameter with the arguments contained in array */
1531
PHP_FUNCTION(forward_static_call_array)
1532
0
{
1533
0
  zval retval;
1534
0
  HashTable *params;
1535
0
  zend_fcall_info fci;
1536
0
  zend_fcall_info_cache fci_cache;
1537
0
  zend_class_entry *called_scope;
1538
1539
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
1540
0
    Z_PARAM_FUNC(fci, fci_cache)
1541
0
    Z_PARAM_ARRAY_HT(params)
1542
0
  ZEND_PARSE_PARAMETERS_END();
1543
1544
0
  fci.retval = &retval;
1545
  /* Add positional arguments */
1546
0
  fci.named_params = params;
1547
1548
0
  called_scope = zend_get_called_scope(execute_data);
1549
0
  if (called_scope && fci_cache.calling_scope &&
1550
0
    instanceof_function(called_scope, fci_cache.calling_scope)) {
1551
0
      fci_cache.called_scope = called_scope;
1552
0
  }
1553
1554
0
  if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1555
0
    if (Z_ISREF(retval)) {
1556
0
      zend_unwrap_reference(&retval);
1557
0
    }
1558
0
    ZVAL_COPY_VALUE(return_value, &retval);
1559
0
  }
1560
0
}
1561
/* }}} */
1562
1563
void user_shutdown_function_dtor(zval *zv) /* {{{ */
1564
28
{
1565
28
  php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
1566
1567
28
  for (uint32_t i = 0; i < shutdown_function_entry->param_count; i++) {
1568
0
    zval_ptr_dtor(&shutdown_function_entry->params[i]);
1569
0
  }
1570
28
  efree(shutdown_function_entry->params);
1571
28
  zend_fcc_dtor(&shutdown_function_entry->fci_cache);
1572
28
  efree(shutdown_function_entry);
1573
28
}
1574
/* }}} */
1575
1576
void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* {{{ */
1577
20
{
1578
20
  for (uint32_t i = 0; i < tick_function_entry->param_count; i++) {
1579
0
    zval_ptr_dtor(&tick_function_entry->params[i]);
1580
0
  }
1581
20
  efree(tick_function_entry->params);
1582
20
  zend_fcc_dtor(&tick_function_entry->fci_cache);
1583
20
}
1584
/* }}} */
1585
1586
static int user_shutdown_function_call(zval *zv) /* {{{ */
1587
28
{
1588
28
  php_shutdown_function_entry *entry = Z_PTR_P(zv);
1589
1590
28
  zend_call_known_fcc(&entry->fci_cache, NULL, entry->param_count, entry->params, NULL);
1591
28
  return 0;
1592
28
}
1593
/* }}} */
1594
1595
static void user_tick_function_call(user_tick_function_entry *tick_fe) /* {{{ */
1596
318
{
1597
  /* Prevent re-entrant calls to the same user ticks function */
1598
318
  if (!tick_fe->calling) {
1599
318
    tick_fe->calling = true;
1600
318
    zend_call_known_fcc(&tick_fe->fci_cache, NULL, tick_fe->param_count, tick_fe->params, NULL);
1601
318
    tick_fe->calling = false;
1602
318
  }
1603
318
}
1604
/* }}} */
1605
1606
static void run_user_tick_functions(int tick_count, void *arg) /* {{{ */
1607
88
{
1608
88
  zend_llist_apply(BG(user_tick_functions), (llist_apply_func_t) user_tick_function_call);
1609
88
}
1610
/* }}} */
1611
1612
static int user_tick_function_compare(user_tick_function_entry * tick_fe1, user_tick_function_entry * tick_fe2) /* {{{ */
1613
0
{
1614
0
  bool is_equal = zend_fcc_equals(&tick_fe1->fci_cache, &tick_fe2->fci_cache);
1615
1616
0
  if (is_equal && tick_fe1->calling) {
1617
0
    zend_throw_error(NULL, "Registered tick function cannot be unregistered while it is being executed");
1618
0
    return false;
1619
0
  }
1620
0
  return is_equal;
1621
0
}
1622
/* }}} */
1623
1624
PHPAPI void php_call_shutdown_functions(void) /* {{{ */
1625
222k
{
1626
222k
  if (BG(user_shutdown_function_names)) {
1627
23
    zend_try {
1628
23
      zend_hash_apply(BG(user_shutdown_function_names), user_shutdown_function_call);
1629
23
    } zend_end_try();
1630
23
  }
1631
222k
}
1632
/* }}} */
1633
1634
PHPAPI void php_free_shutdown_functions(void) /* {{{ */
1635
222k
{
1636
222k
  if (BG(user_shutdown_function_names))
1637
23
    zend_try {
1638
23
      zend_hash_destroy(BG(user_shutdown_function_names));
1639
23
      FREE_HASHTABLE(BG(user_shutdown_function_names));
1640
23
      BG(user_shutdown_function_names) = NULL;
1641
23
    } zend_catch {
1642
      /* maybe shutdown method call exit, we just ignore it */
1643
0
      FREE_HASHTABLE(BG(user_shutdown_function_names));
1644
0
      BG(user_shutdown_function_names) = NULL;
1645
0
    } zend_end_try();
1646
222k
}
1647
/* }}} */
1648
1649
/* {{{ Register a user-level function to be called on request termination */
1650
PHP_FUNCTION(register_shutdown_function)
1651
29
{
1652
29
  zend_fcall_info fci;
1653
29
  php_shutdown_function_entry entry = {
1654
29
    .fci_cache = empty_fcall_info_cache,
1655
29
    .params = NULL,
1656
29
    .param_count = 0,
1657
29
  };
1658
29
  zval *params = NULL;
1659
29
  bool status;
1660
1661
29
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "F*", &fci, &entry.fci_cache, &params, &entry.param_count) == FAILURE) {
1662
1
    RETURN_THROWS();
1663
1
  }
1664
1665
28
  zend_fcc_addref(&entry.fci_cache);
1666
28
  if (entry.param_count) {
1667
0
    ZEND_ASSERT(params != NULL);
1668
0
    entry.params = (zval *) safe_emalloc(entry.param_count, sizeof(zval), 0);
1669
0
    for (uint32_t i = 0; i < entry.param_count; i++) {
1670
0
      ZVAL_COPY(&entry.params[i], &params[i]);
1671
0
    }
1672
0
  }
1673
1674
28
  status = append_user_shutdown_function(&entry);
1675
28
  ZEND_ASSERT(status);
1676
28
}
1677
/* }}} */
1678
1679
PHPAPI bool register_user_shutdown_function(const char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
1680
0
{
1681
0
  if (!BG(user_shutdown_function_names)) {
1682
0
    ALLOC_HASHTABLE(BG(user_shutdown_function_names));
1683
0
    zend_hash_init(BG(user_shutdown_function_names), 0, NULL, user_shutdown_function_dtor, 0);
1684
0
  }
1685
1686
0
  zend_hash_str_update_mem(BG(user_shutdown_function_names), function_name, function_len, shutdown_function_entry, sizeof(php_shutdown_function_entry));
1687
0
  return 1;
1688
0
}
1689
/* }}} */
1690
1691
PHPAPI bool remove_user_shutdown_function(const char *function_name, size_t function_len) /* {{{ */
1692
0
{
1693
0
  if (BG(user_shutdown_function_names)) {
1694
0
    return zend_hash_str_del(BG(user_shutdown_function_names), function_name, function_len) != FAILURE;
1695
0
  }
1696
1697
0
  return 0;
1698
0
}
1699
/* }}} */
1700
1701
PHPAPI bool append_user_shutdown_function(php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
1702
28
{
1703
28
  if (!BG(user_shutdown_function_names)) {
1704
23
    ALLOC_HASHTABLE(BG(user_shutdown_function_names));
1705
23
    zend_hash_init(BG(user_shutdown_function_names), 0, NULL, user_shutdown_function_dtor, 0);
1706
23
  }
1707
1708
28
  return zend_hash_next_index_insert_mem(BG(user_shutdown_function_names), shutdown_function_entry, sizeof(php_shutdown_function_entry)) != NULL;
1709
28
}
1710
/* }}} */
1711
1712
ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini) /* {{{ */
1713
5.04k
{
1714
5.04k
  syntax_highlighter_ini->highlight_comment = INI_STR("highlight.comment");
1715
5.04k
  syntax_highlighter_ini->highlight_default = INI_STR("highlight.default");
1716
5.04k
  syntax_highlighter_ini->highlight_html    = INI_STR("highlight.html");
1717
5.04k
  syntax_highlighter_ini->highlight_keyword = INI_STR("highlight.keyword");
1718
5.04k
  syntax_highlighter_ini->highlight_string  = INI_STR("highlight.string");
1719
5.04k
}
1720
/* }}} */
1721
1722
/* {{{ Syntax highlight a source file */
1723
PHP_FUNCTION(highlight_file)
1724
0
{
1725
0
  char *filename;
1726
0
  size_t filename_len;
1727
0
  int ret;
1728
0
  zend_syntax_highlighter_ini syntax_highlighter_ini;
1729
0
  bool i = 0;
1730
1731
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
1732
0
    Z_PARAM_PATH(filename, filename_len)
1733
0
    Z_PARAM_OPTIONAL
1734
0
    Z_PARAM_BOOL(i)
1735
0
  ZEND_PARSE_PARAMETERS_END();
1736
1737
0
  if (php_check_open_basedir(filename)) {
1738
0
    RETURN_FALSE;
1739
0
  }
1740
1741
0
  if (i) {
1742
0
    php_output_start_default();
1743
0
  }
1744
1745
0
  php_get_highlight_struct(&syntax_highlighter_ini);
1746
1747
0
  ret = highlight_file(filename, &syntax_highlighter_ini);
1748
1749
0
  if (ret == FAILURE) {
1750
0
    if (i) {
1751
0
      php_output_end();
1752
0
    }
1753
0
    RETURN_FALSE;
1754
0
  }
1755
1756
0
  if (i) {
1757
0
    php_output_get_contents(return_value);
1758
0
    php_output_discard();
1759
0
    ZEND_ASSERT(Z_TYPE_P(return_value) == IS_STRING);
1760
0
  } else {
1761
0
    RETURN_TRUE;
1762
0
  }
1763
0
}
1764
/* }}} */
1765
1766
/* {{{ Return source with stripped comments and whitespace */
1767
PHP_FUNCTION(php_strip_whitespace)
1768
0
{
1769
0
  zend_string *filename;
1770
0
  zend_lex_state original_lex_state;
1771
0
  zend_file_handle file_handle;
1772
1773
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1774
0
    Z_PARAM_PATH_STR(filename)
1775
0
  ZEND_PARSE_PARAMETERS_END();
1776
1777
0
  php_output_start_default();
1778
1779
0
  zend_stream_init_filename_ex(&file_handle, filename);
1780
0
  zend_save_lexical_state(&original_lex_state);
1781
0
  if (open_file_for_scanning(&file_handle) == FAILURE) {
1782
0
    zend_restore_lexical_state(&original_lex_state);
1783
0
    php_output_end();
1784
0
    zend_destroy_file_handle(&file_handle);
1785
0
    RETURN_EMPTY_STRING();
1786
0
  }
1787
1788
0
  zend_strip();
1789
1790
0
  zend_restore_lexical_state(&original_lex_state);
1791
1792
0
  php_output_get_contents(return_value);
1793
0
  php_output_discard();
1794
0
  zend_destroy_file_handle(&file_handle);
1795
0
}
1796
/* }}} */
1797
1798
/* {{{ Syntax highlight a string or optionally return it */
1799
PHP_FUNCTION(highlight_string)
1800
5.04k
{
1801
5.04k
  zend_string *str;
1802
5.04k
  zend_syntax_highlighter_ini syntax_highlighter_ini;
1803
5.04k
  char *hicompiled_string_description;
1804
5.04k
  bool i = 0;
1805
5.04k
  int old_error_reporting = EG(error_reporting);
1806
1807
15.1k
  ZEND_PARSE_PARAMETERS_START(1, 2)
1808
20.1k
    Z_PARAM_STR(str)
1809
5.04k
    Z_PARAM_OPTIONAL
1810
10.9k
    Z_PARAM_BOOL(i)
1811
5.04k
  ZEND_PARSE_PARAMETERS_END();
1812
1813
5.04k
  if (i) {
1814
435
    php_output_start_default();
1815
435
  }
1816
1817
5.04k
  EG(error_reporting) = E_ERROR;
1818
1819
5.04k
  php_get_highlight_struct(&syntax_highlighter_ini);
1820
1821
5.04k
  hicompiled_string_description = zend_make_compiled_string_description("highlighted code");
1822
1823
5.04k
  highlight_string(str, &syntax_highlighter_ini, hicompiled_string_description);
1824
5.04k
  efree(hicompiled_string_description);
1825
1826
5.04k
  EG(error_reporting) = old_error_reporting;
1827
1828
5.04k
  if (i) {
1829
435
    php_output_get_contents(return_value);
1830
435
    php_output_discard();
1831
435
    ZEND_ASSERT(Z_TYPE_P(return_value) == IS_STRING);
1832
4.60k
  } else {
1833
    // TODO Make this function void?
1834
4.60k
    RETURN_TRUE;
1835
4.60k
  }
1836
5.04k
}
1837
/* }}} */
1838
1839
/* {{{ Get interpreted size from the ini shorthand syntax */
1840
PHP_FUNCTION(ini_parse_quantity)
1841
1
{
1842
1
  zend_string *shorthand;
1843
1
  zend_string *errstr;
1844
1845
3
  ZEND_PARSE_PARAMETERS_START(1, 1)
1846
4
    Z_PARAM_STR(shorthand)
1847
1
  ZEND_PARSE_PARAMETERS_END();
1848
1849
1
  RETVAL_LONG(zend_ini_parse_quantity(shorthand, &errstr));
1850
1851
1
  if (errstr) {
1852
0
    zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
1853
0
    zend_string_release(errstr);
1854
0
  }
1855
1
}
1856
/* }}} */
1857
1858
/* {{{ Get a configuration option */
1859
PHP_FUNCTION(ini_get)
1860
14
{
1861
14
  zend_string *varname, *val;
1862
1863
42
  ZEND_PARSE_PARAMETERS_START(1, 1)
1864
56
    Z_PARAM_STR(varname)
1865
14
  ZEND_PARSE_PARAMETERS_END();
1866
1867
14
  val = zend_ini_get_value(varname);
1868
1869
14
  if (!val) {
1870
4
    RETURN_FALSE;
1871
4
  }
1872
1873
10
  ZVAL_SET_INI_STR(return_value, val);
1874
10
}
1875
/* }}} */
1876
1877
/* {{{ Get all configuration options */
1878
PHP_FUNCTION(ini_get_all)
1879
0
{
1880
0
  zend_string *extname = NULL;
1881
0
  size_t module_number = 0;
1882
0
  zend_module_entry *module;
1883
0
  bool details = 1;
1884
0
  zend_string *key;
1885
0
  zend_ini_entry *ini_entry;
1886
1887
1888
0
  ZEND_PARSE_PARAMETERS_START(0, 2)
1889
0
    Z_PARAM_OPTIONAL
1890
0
    Z_PARAM_STR_OR_NULL(extname)
1891
0
    Z_PARAM_BOOL(details)
1892
0
  ZEND_PARSE_PARAMETERS_END();
1893
1894
0
  zend_ini_sort_entries();
1895
1896
0
  if (extname) {
1897
0
    if ((module = zend_hash_find_ptr(&module_registry, extname)) == NULL) {
1898
0
      php_error_docref(NULL, E_WARNING, "Extension \"%s\" cannot be found", ZSTR_VAL(extname));
1899
0
      RETURN_FALSE;
1900
0
    }
1901
0
    module_number = module->module_number;
1902
0
  }
1903
1904
0
  array_init(return_value);
1905
0
  ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(ini_directives), key, ini_entry) {
1906
0
    zval option;
1907
1908
0
    if (module_number != 0 && ini_entry->module_number != module_number) {
1909
0
      continue;
1910
0
    }
1911
1912
0
    if (key == NULL || ZSTR_VAL(key)[0] != 0) {
1913
0
      if (details) {
1914
0
        array_init(&option);
1915
1916
0
        if (ini_entry->orig_value) {
1917
0
          add_assoc_str(&option, "global_value", zend_string_copy(ini_entry->orig_value));
1918
0
        } else if (ini_entry->value) {
1919
0
          add_assoc_str(&option, "global_value", zend_string_copy(ini_entry->value));
1920
0
        } else {
1921
0
          add_assoc_null(&option, "global_value");
1922
0
        }
1923
1924
0
        if (ini_entry->value) {
1925
0
          add_assoc_str(&option, "local_value", zend_string_copy(ini_entry->value));
1926
0
        } else {
1927
0
          add_assoc_null(&option, "local_value");
1928
0
        }
1929
1930
0
        add_assoc_long(&option, "access", ini_entry->modifiable);
1931
1932
0
        zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &option);
1933
0
      } else {
1934
0
        if (ini_entry->value) {
1935
0
          zval zv;
1936
1937
0
          ZVAL_STR_COPY(&zv, ini_entry->value);
1938
0
          zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &zv);
1939
0
        } else {
1940
0
          zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &EG(uninitialized_zval));
1941
0
        }
1942
0
      }
1943
0
    }
1944
0
  } ZEND_HASH_FOREACH_END();
1945
0
}
1946
/* }}} */
1947
1948
/* {{{ Set a configuration option, returns false on error and the old value of the configuration option on success */
1949
PHP_FUNCTION(ini_set)
1950
578
{
1951
578
  zend_string *varname;
1952
578
  zval *new_value;
1953
578
  zend_string *val;
1954
1955
1.73k
  ZEND_PARSE_PARAMETERS_START(2, 2)
1956
2.30k
    Z_PARAM_STR(varname)
1957
2.88k
    Z_PARAM_ZVAL(new_value)
1958
2.88k
  ZEND_PARSE_PARAMETERS_END();
1959
1960
577
  if (Z_TYPE_P(new_value) > IS_STRING) {
1961
0
    zend_argument_type_error(2, "must be of type string|int|float|bool|null");
1962
0
    RETURN_THROWS();
1963
0
  }
1964
1965
577
  val = zend_ini_get_value(varname);
1966
1967
577
  if (val) {
1968
70
    ZVAL_SET_INI_STR(return_value, val);
1969
507
  } else {
1970
507
    RETVAL_FALSE;
1971
507
  }
1972
1973
577
  zend_string *new_value_tmp_str;
1974
577
  zend_string *new_value_str = zval_get_tmp_string(new_value, &new_value_tmp_str);
1975
1976
  /* open basedir check */
1977
577
  if (PG(open_basedir)) {
1978
577
    if (
1979
577
      zend_string_equals_literal(varname, "java.class.path")
1980
577
      || zend_string_equals_literal(varname, "java.home")
1981
577
      || zend_string_equals_literal(varname, "java.library.path")
1982
577
      || zend_string_equals_literal(varname, "vpopmail.directory")
1983
577
    ) {
1984
0
      if (php_check_open_basedir(ZSTR_VAL(new_value_str))) {
1985
0
        zval_ptr_dtor_str(return_value);
1986
0
        zend_tmp_string_release(new_value_tmp_str);
1987
0
        RETURN_FALSE;
1988
0
      }
1989
0
    }
1990
577
  }
1991
1992
577
  if (zend_alter_ini_entry_ex(varname, new_value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) {
1993
537
    zval_ptr_dtor_str(return_value);
1994
537
    RETVAL_FALSE;
1995
537
  }
1996
577
  zend_tmp_string_release(new_value_tmp_str);
1997
577
}
1998
/* }}} */
1999
2000
/* {{{ Restore the value of a configuration option specified by varname */
2001
PHP_FUNCTION(ini_restore)
2002
0
{
2003
0
  zend_string *varname;
2004
2005
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2006
0
    Z_PARAM_STR(varname)
2007
0
  ZEND_PARSE_PARAMETERS_END();
2008
2009
0
  zend_restore_ini_entry(varname, PHP_INI_STAGE_RUNTIME);
2010
0
}
2011
/* }}} */
2012
2013
/* {{{ Sets the include_path configuration option */
2014
PHP_FUNCTION(set_include_path)
2015
5
{
2016
5
  zend_string *new_value;
2017
5
  char *old_value;
2018
5
  zend_string *key;
2019
2020
15
  ZEND_PARSE_PARAMETERS_START(1, 1)
2021
20
    Z_PARAM_PATH_STR(new_value)
2022
5
  ZEND_PARSE_PARAMETERS_END();
2023
2024
5
  old_value = zend_ini_string("include_path", sizeof("include_path") - 1, 0);
2025
  /* copy to return here, because alter might free it! */
2026
5
  if (old_value) {
2027
5
    RETVAL_STRING(old_value);
2028
5
  } else {
2029
0
    RETVAL_FALSE;
2030
0
  }
2031
2032
5
  key = ZSTR_INIT_LITERAL("include_path", 0);
2033
5
  if (zend_alter_ini_entry_ex(key, new_value, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) {
2034
0
    zend_string_release_ex(key, 0);
2035
0
    zval_ptr_dtor_str(return_value);
2036
0
    RETURN_FALSE;
2037
0
  }
2038
5
  zend_string_release_ex(key, 0);
2039
5
}
2040
/* }}} */
2041
2042
/* {{{ Get the current include_path configuration option */
2043
PHP_FUNCTION(get_include_path)
2044
0
{
2045
0
  ZEND_PARSE_PARAMETERS_NONE();
2046
2047
0
  zend_string *str = zend_ini_str("include_path", sizeof("include_path") - 1, 0);
2048
2049
0
  if (str == NULL) {
2050
0
    RETURN_FALSE;
2051
0
  }
2052
2053
0
  RETURN_STR_COPY(str);
2054
0
}
2055
/* }}} */
2056
2057
/* {{{ Prints out or returns information about the specified variable */
2058
PHP_FUNCTION(print_r)
2059
978
{
2060
978
  zval *var;
2061
978
  bool do_return = 0;
2062
2063
2.93k
  ZEND_PARSE_PARAMETERS_START(1, 2)
2064
3.91k
    Z_PARAM_ZVAL(var)
2065
3.91k
    Z_PARAM_OPTIONAL
2066
3.91k
    Z_PARAM_BOOL(do_return)
2067
978
  ZEND_PARSE_PARAMETERS_END();
2068
2069
978
  if (do_return) {
2070
6
    RETURN_STR(zend_print_zval_r_to_str(var, 0));
2071
972
  } else {
2072
972
    zend_print_zval_r(var, 0);
2073
972
    RETURN_TRUE;
2074
972
  }
2075
978
}
2076
/* }}} */
2077
2078
/* {{{ Returns true if client disconnected */
2079
PHP_FUNCTION(connection_aborted)
2080
0
{
2081
0
  ZEND_PARSE_PARAMETERS_NONE();
2082
2083
0
  RETURN_LONG(PG(connection_status) & PHP_CONNECTION_ABORTED);
2084
0
}
2085
/* }}} */
2086
2087
/* {{{ Returns the connection status bitfield */
2088
PHP_FUNCTION(connection_status)
2089
0
{
2090
0
  ZEND_PARSE_PARAMETERS_NONE();
2091
2092
0
  RETURN_LONG(PG(connection_status));
2093
0
}
2094
/* }}} */
2095
2096
/* {{{ Set whether we want to ignore a user abort event or not */
2097
PHP_FUNCTION(ignore_user_abort)
2098
0
{
2099
0
  bool arg = 0;
2100
0
  bool arg_is_null = 1;
2101
0
  int old_setting;
2102
2103
0
  ZEND_PARSE_PARAMETERS_START(0, 1)
2104
0
    Z_PARAM_OPTIONAL
2105
0
    Z_PARAM_BOOL_OR_NULL(arg, arg_is_null)
2106
0
  ZEND_PARSE_PARAMETERS_END();
2107
2108
0
  old_setting = (unsigned short)PG(ignore_user_abort);
2109
2110
0
  if (!arg_is_null) {
2111
0
    zend_string *key = ZSTR_INIT_LITERAL("ignore_user_abort", 0);
2112
0
    zend_alter_ini_entry_chars(key, arg ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
2113
0
    zend_string_release_ex(key, 0);
2114
0
  }
2115
2116
0
  RETURN_LONG(old_setting);
2117
0
}
2118
/* }}} */
2119
2120
#ifdef HAVE_GETSERVBYNAME
2121
/* {{{ Returns port associated with service. Protocol must be "tcp" or "udp" */
2122
PHP_FUNCTION(getservbyname)
2123
0
{
2124
0
  zend_string *name;
2125
0
  char *proto;
2126
0
  size_t proto_len;
2127
0
  struct servent *serv;
2128
2129
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
2130
0
    Z_PARAM_PATH_STR(name)
2131
0
    Z_PARAM_PATH(proto, proto_len)
2132
0
  ZEND_PARSE_PARAMETERS_END();
2133
2134
2135
/* empty string behaves like NULL on windows implementation of
2136
   getservbyname. Let be portable instead. */
2137
#ifdef PHP_WIN32
2138
  if (proto_len == 0) {
2139
    RETURN_FALSE;
2140
  }
2141
#endif
2142
2143
0
  serv = getservbyname(ZSTR_VAL(name), proto);
2144
2145
#ifdef _AIX
2146
  /*
2147
        On AIX, imap is only known as imap2 in /etc/services, while on Linux imap is an alias for imap2.
2148
        If a request for imap gives no result, we try again with imap2.
2149
        */
2150
  if (serv == NULL && zend_string_equals_literal(name, "imap")) {
2151
    serv = getservbyname("imap2", proto);
2152
  }
2153
#endif
2154
0
  if (serv == NULL) {
2155
0
    RETURN_FALSE;
2156
0
  }
2157
2158
0
  RETURN_LONG(ntohs(serv->s_port));
2159
0
}
2160
/* }}} */
2161
#endif
2162
2163
#ifdef HAVE_GETSERVBYPORT
2164
/* {{{ Returns service name associated with port. Protocol must be "tcp" or "udp" */
2165
PHP_FUNCTION(getservbyport)
2166
0
{
2167
0
  char *proto;
2168
0
  size_t proto_len;
2169
0
  zend_long port;
2170
0
  struct servent *serv;
2171
2172
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
2173
0
    Z_PARAM_LONG(port)
2174
0
    Z_PARAM_PATH(proto, proto_len)
2175
0
  ZEND_PARSE_PARAMETERS_END();
2176
2177
0
  serv = getservbyport(htons((unsigned short) port), proto);
2178
2179
0
  if (serv == NULL) {
2180
0
    RETURN_FALSE;
2181
0
  }
2182
2183
  /* MSAN false positive, getservbyport() is not properly intercepted. */
2184
#if __has_feature(memory_sanitizer)
2185
  __msan_unpoison_string(serv->s_name);
2186
#endif
2187
0
  RETURN_STRING(serv->s_name);
2188
0
}
2189
/* }}} */
2190
#endif
2191
2192
#ifdef HAVE_GETPROTOBYNAME
2193
/* {{{ Returns protocol number associated with name as per /etc/protocols */
2194
PHP_FUNCTION(getprotobyname)
2195
0
{
2196
0
  char *name;
2197
0
  size_t name_len;
2198
0
  struct protoent *ent;
2199
2200
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2201
0
    Z_PARAM_PATH(name, name_len)
2202
0
  ZEND_PARSE_PARAMETERS_END();
2203
2204
0
  ent = getprotobyname(name);
2205
2206
0
  if (ent == NULL) {
2207
0
    RETURN_FALSE;
2208
0
  }
2209
2210
0
  RETURN_LONG(ent->p_proto);
2211
0
}
2212
/* }}} */
2213
#endif
2214
2215
#ifdef HAVE_GETPROTOBYNUMBER
2216
/* {{{ Returns protocol name associated with protocol number proto */
2217
PHP_FUNCTION(getprotobynumber)
2218
0
{
2219
0
  zend_long proto;
2220
0
  struct protoent *ent;
2221
2222
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2223
0
    Z_PARAM_LONG(proto)
2224
0
  ZEND_PARSE_PARAMETERS_END();
2225
2226
0
  ent = getprotobynumber((int)proto);
2227
2228
0
  if (ent == NULL) {
2229
0
    RETURN_FALSE;
2230
0
  }
2231
2232
0
  RETURN_STRING(ent->p_name);
2233
0
}
2234
/* }}} */
2235
#endif
2236
2237
/* {{{ Registers a tick callback function */
2238
PHP_FUNCTION(register_tick_function)
2239
20
{
2240
20
  user_tick_function_entry tick_fe = {
2241
20
    .fci_cache = empty_fcall_info_cache,
2242
20
    .params = NULL,
2243
20
    .param_count = 0,
2244
20
    .calling = false,
2245
20
  };
2246
20
  zend_fcall_info fci;
2247
20
  zval *params = NULL;
2248
2249
20
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "F*", &fci, &tick_fe.fci_cache, &params, &tick_fe.param_count) == FAILURE) {
2250
0
    RETURN_THROWS();
2251
0
  }
2252
2253
20
  zend_fcc_addref(&tick_fe.fci_cache);
2254
20
  if (tick_fe.param_count) {
2255
0
    ZEND_ASSERT(params != NULL);
2256
0
    tick_fe.params = (zval *) safe_emalloc(tick_fe.param_count, sizeof(zval), 0);
2257
0
    for (uint32_t i = 0; i < tick_fe.param_count; i++) {
2258
0
      ZVAL_COPY(&tick_fe.params[i], &params[i]);
2259
0
    }
2260
0
  }
2261
2262
20
  if (!BG(user_tick_functions)) {
2263
8
    BG(user_tick_functions) = (zend_llist *) emalloc(sizeof(zend_llist));
2264
8
    zend_llist_init(BG(user_tick_functions),
2265
8
            sizeof(user_tick_function_entry),
2266
8
            (llist_dtor_func_t) user_tick_function_dtor, 0);
2267
8
    php_add_tick_function(run_user_tick_functions, NULL);
2268
8
  }
2269
2270
20
  zend_llist_add_element(BG(user_tick_functions), &tick_fe);
2271
2272
20
  RETURN_TRUE;
2273
20
}
2274
/* }}} */
2275
2276
/* {{{ Unregisters a tick callback function */
2277
PHP_FUNCTION(unregister_tick_function)
2278
0
{
2279
0
  user_tick_function_entry tick_fe = {
2280
0
    .fci_cache = empty_fcall_info_cache,
2281
0
    .params = NULL,
2282
0
    .param_count = 0,
2283
0
    .calling = false,
2284
0
  };
2285
0
  zend_fcall_info fci;
2286
2287
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2288
0
    Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, tick_fe.fci_cache)
2289
0
  ZEND_PARSE_PARAMETERS_END();
2290
2291
0
  if (BG(user_tick_functions)) {
2292
0
    zend_llist_del_element(BG(user_tick_functions), &tick_fe, (int (*)(void *, void *)) user_tick_function_compare);
2293
0
  }
2294
2295
  /* Free potential trampoline */
2296
0
  zend_release_fcall_info_cache(&tick_fe.fci_cache);
2297
0
}
2298
/* }}} */
2299
2300
/* {{{ Check if file was created by rfc1867 upload */
2301
PHP_FUNCTION(is_uploaded_file)
2302
0
{
2303
0
  zend_string *path;
2304
2305
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2306
0
    Z_PARAM_PATH_STR(path)
2307
0
  ZEND_PARSE_PARAMETERS_END();
2308
2309
0
  if (!SG(rfc1867_uploaded_files)) {
2310
0
    RETURN_FALSE;
2311
0
  }
2312
2313
0
  RETURN_BOOL(zend_hash_exists(SG(rfc1867_uploaded_files), path));
2314
0
}
2315
/* }}} */
2316
2317
/* {{{ Move a file if and only if it was created by an upload */
2318
PHP_FUNCTION(move_uploaded_file)
2319
0
{
2320
0
  zend_string *path, *new_path;
2321
0
  bool successful = 0;
2322
2323
0
#ifndef PHP_WIN32
2324
0
  int oldmask; int ret;
2325
0
#endif
2326
2327
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
2328
0
    Z_PARAM_PATH_STR(path)
2329
0
    Z_PARAM_PATH_STR(new_path)
2330
0
  ZEND_PARSE_PARAMETERS_END();
2331
2332
0
  if (!SG(rfc1867_uploaded_files)) {
2333
0
    RETURN_FALSE;
2334
0
  }
2335
2336
0
  if (!zend_hash_exists(SG(rfc1867_uploaded_files), path)) {
2337
0
    RETURN_FALSE;
2338
0
  }
2339
2340
0
  if (php_check_open_basedir(ZSTR_VAL(new_path))) {
2341
0
    RETURN_FALSE;
2342
0
  }
2343
2344
0
  if (VCWD_RENAME(ZSTR_VAL(path), ZSTR_VAL(new_path)) == 0) {
2345
0
    successful = 1;
2346
0
#ifndef PHP_WIN32
2347
0
    oldmask = umask(077);
2348
0
    umask(oldmask);
2349
2350
0
    ret = VCWD_CHMOD(ZSTR_VAL(new_path), 0666 & ~oldmask);
2351
2352
0
    if (ret == -1) {
2353
0
      php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
2354
0
    }
2355
0
#endif
2356
0
  } else if (php_copy_file_ex(ZSTR_VAL(path), ZSTR_VAL(new_path), STREAM_DISABLE_OPEN_BASEDIR) == SUCCESS) {
2357
0
    VCWD_UNLINK(ZSTR_VAL(path));
2358
0
    successful = 1;
2359
0
  }
2360
2361
0
  if (successful) {
2362
0
    zend_hash_del(SG(rfc1867_uploaded_files), path);
2363
0
  } else {
2364
0
    php_error_docref(NULL, E_WARNING, "Unable to move \"%s\" to \"%s\"", ZSTR_VAL(path), ZSTR_VAL(new_path));
2365
0
  }
2366
2367
0
  RETURN_BOOL(successful);
2368
0
}
2369
/* }}} */
2370
2371
/* {{{ php_simple_ini_parser_cb */
2372
static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr)
2373
150k
{
2374
150k
  switch (callback_type) {
2375
2376
146k
    case ZEND_INI_PARSER_ENTRY:
2377
146k
      if (!arg2) {
2378
        /* bare string - nothing to do */
2379
50.2k
        break;
2380
50.2k
      }
2381
96.0k
      Z_TRY_ADDREF_P(arg2);
2382
96.0k
      zend_symtable_update(Z_ARRVAL_P(arr), Z_STR_P(arg1), arg2);
2383
96.0k
      break;
2384
2385
198
    case ZEND_INI_PARSER_POP_ENTRY:
2386
198
    {
2387
198
      zval hash, *find_hash;
2388
2389
198
      if (!arg2) {
2390
        /* bare string - nothing to do */
2391
0
        break;
2392
0
      }
2393
2394
      /* entry in the form x[a]=b where x might need to be an array index */
2395
198
      if (!(Z_STRLEN_P(arg1) > 1 && Z_STRVAL_P(arg1)[0] == '0') && is_numeric_string(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), NULL, NULL, 0) == IS_LONG) {
2396
0
        zend_ulong key = (zend_ulong) ZEND_STRTOUL(Z_STRVAL_P(arg1), NULL, 0);
2397
0
        if ((find_hash = zend_hash_index_find(Z_ARRVAL_P(arr), key)) == NULL) {
2398
0
          array_init(&hash);
2399
0
          find_hash = zend_hash_index_add_new(Z_ARRVAL_P(arr), key, &hash);
2400
0
        }
2401
198
      } else {
2402
198
        if ((find_hash = zend_hash_find(Z_ARRVAL_P(arr), Z_STR_P(arg1))) == NULL) {
2403
198
          array_init(&hash);
2404
198
          find_hash = zend_hash_add_new(Z_ARRVAL_P(arr), Z_STR_P(arg1), &hash);
2405
198
        }
2406
198
      }
2407
2408
198
      if (Z_TYPE_P(find_hash) != IS_ARRAY) {
2409
0
        zval_ptr_dtor_nogc(find_hash);
2410
0
        array_init(find_hash);
2411
0
      }
2412
2413
198
      if (!arg3 || (Z_TYPE_P(arg3) == IS_STRING && Z_STRLEN_P(arg3) == 0)) {
2414
0
        Z_TRY_ADDREF_P(arg2);
2415
0
        add_next_index_zval(find_hash, arg2);
2416
198
      } else {
2417
198
        array_set_zval_key(Z_ARRVAL_P(find_hash), arg3, arg2);
2418
198
      }
2419
198
    }
2420
0
    break;
2421
2422
4.45k
    case ZEND_INI_PARSER_SECTION:
2423
4.45k
      break;
2424
150k
  }
2425
150k
}
2426
/* }}} */
2427
2428
/* {{{ php_ini_parser_cb_with_sections */
2429
static void php_ini_parser_cb_with_sections(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr)
2430
2.23k
{
2431
2.23k
  if (callback_type == ZEND_INI_PARSER_SECTION) {
2432
121
    array_init(&BG(active_ini_file_section));
2433
121
    zend_symtable_update(Z_ARRVAL_P(arr), Z_STR_P(arg1), &BG(active_ini_file_section));
2434
2.11k
  } else if (arg2) {
2435
914
    zval *active_arr;
2436
2437
914
    if (Z_TYPE(BG(active_ini_file_section)) != IS_UNDEF) {
2438
626
      active_arr = &BG(active_ini_file_section);
2439
626
    } else {
2440
288
      active_arr = arr;
2441
288
    }
2442
2443
914
    php_simple_ini_parser_cb(arg1, arg2, arg3, callback_type, active_arr);
2444
914
  }
2445
2.23k
}
2446
/* }}} */
2447
2448
/* {{{ Parse configuration file */
2449
PHP_FUNCTION(parse_ini_file)
2450
2
{
2451
2
  zend_string *filename = NULL;
2452
2
  bool process_sections = 0;
2453
2
  zend_long scanner_mode = ZEND_INI_SCANNER_NORMAL;
2454
2
  zend_file_handle fh;
2455
2
  zend_ini_parser_cb_t ini_parser_cb;
2456
2457
6
  ZEND_PARSE_PARAMETERS_START(1, 3)
2458
8
    Z_PARAM_PATH_STR(filename)
2459
2
    Z_PARAM_OPTIONAL
2460
8
    Z_PARAM_BOOL(process_sections)
2461
10
    Z_PARAM_LONG(scanner_mode)
2462
2
  ZEND_PARSE_PARAMETERS_END();
2463
2464
2
  if (ZSTR_LEN(filename) == 0) {
2465
0
    zend_argument_must_not_be_empty_error(1);
2466
0
    RETURN_THROWS();
2467
0
  }
2468
2469
  /* Set callback function */
2470
2
  if (process_sections) {
2471
1
    ZVAL_UNDEF(&BG(active_ini_file_section));
2472
1
    ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections;
2473
1
  } else {
2474
1
    ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb;
2475
1
  }
2476
2477
  /* Setup filehandle */
2478
2
  zend_stream_init_filename_ex(&fh, filename);
2479
2480
2
  array_init(return_value);
2481
2
  if (zend_parse_ini_file(&fh, 0, (int)scanner_mode, ini_parser_cb, return_value) == FAILURE) {
2482
2
    zend_array_destroy(Z_ARR_P(return_value));
2483
2
    RETVAL_FALSE;
2484
2
  }
2485
2
  zend_destroy_file_handle(&fh);
2486
2
}
2487
/* }}} */
2488
2489
/* {{{ Parse configuration string */
2490
PHP_FUNCTION(parse_ini_string)
2491
15.7k
{
2492
15.7k
  char *string = NULL, *str = NULL;
2493
15.7k
  size_t str_len = 0;
2494
15.7k
  bool process_sections = 0;
2495
15.7k
  zend_long scanner_mode = ZEND_INI_SCANNER_NORMAL;
2496
15.7k
  zend_ini_parser_cb_t ini_parser_cb;
2497
2498
47.1k
  ZEND_PARSE_PARAMETERS_START(1, 3)
2499
62.8k
    Z_PARAM_STRING(str, str_len)
2500
15.7k
    Z_PARAM_OPTIONAL
2501
32.5k
    Z_PARAM_BOOL(process_sections)
2502
2.81k
    Z_PARAM_LONG(scanner_mode)
2503
15.7k
  ZEND_PARSE_PARAMETERS_END();
2504
2505
15.7k
  if (INT_MAX - str_len < ZEND_MMAP_AHEAD) {
2506
0
    RETVAL_FALSE;
2507
0
  }
2508
2509
  /* Set callback function */
2510
15.7k
  if (process_sections) {
2511
374
    ZVAL_UNDEF(&BG(active_ini_file_section));
2512
374
    ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections;
2513
15.3k
  } else {
2514
15.3k
    ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb;
2515
15.3k
  }
2516
2517
  /* Setup string */
2518
15.7k
  string = (char *) emalloc(str_len + ZEND_MMAP_AHEAD);
2519
15.7k
  memcpy(string, str, str_len);
2520
15.7k
  memset(string + str_len, 0, ZEND_MMAP_AHEAD);
2521
2522
15.7k
  array_init(return_value);
2523
15.7k
  if (zend_parse_ini_string(string, 0, (int)scanner_mode, ini_parser_cb, return_value) == FAILURE) {
2524
10.2k
    zend_array_destroy(Z_ARR_P(return_value));
2525
10.2k
    RETVAL_FALSE;
2526
10.2k
  }
2527
15.7k
  efree(string);
2528
15.7k
}
2529
/* }}} */
2530
2531
#if ZEND_DEBUG
2532
/* This function returns an array of ALL valid ini options with values and
2533
 *  is not the same as ini_get_all() which returns only registered ini options. Only useful for devs to debug php.ini scanner/parser! */
2534
PHP_FUNCTION(config_get_hash) /* {{{ */
2535
0
{
2536
0
  ZEND_PARSE_PARAMETERS_NONE();
2537
2538
0
  HashTable *hash = php_ini_get_configuration_hash();
2539
2540
0
  array_init(return_value);
2541
0
  add_config_entries(hash, return_value);
2542
0
}
2543
/* }}} */
2544
#endif
2545
2546
#ifdef HAVE_GETLOADAVG
2547
/* {{{ */
2548
PHP_FUNCTION(sys_getloadavg)
2549
0
{
2550
0
  double load[3];
2551
2552
0
  ZEND_PARSE_PARAMETERS_NONE();
2553
2554
0
  if (getloadavg(load, 3) == -1) {
2555
0
    RETURN_FALSE;
2556
0
  } else {
2557
0
    array_init(return_value);
2558
0
    add_index_double(return_value, 0, load[0]);
2559
0
    add_index_double(return_value, 1, load[1]);
2560
0
    add_index_double(return_value, 2, load[2]);
2561
0
  }
2562
0
}
2563
/* }}} */
2564
#endif