Coverage Report

Created: 2026-09-14 06:25

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