Coverage Report

Created: 2025-12-14 06:09

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