Coverage Report

Created: 2026-07-25 06:39

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