Coverage Report

Created: 2025-07-23 06:33

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