Coverage Report

Created: 2026-04-01 06:49

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 "SAPI.h"
106
#include "php_ticks.h"
107
108
#ifdef ZTS
109
PHPAPI int basic_globals_id;
110
#else
111
PHPAPI php_basic_globals basic_globals;
112
#endif
113
114
#include "php_fopen_wrappers.h"
115
#include "streamsfuncs.h"
116
#include "zend_frameless_function.h"
117
#include "basic_functions_arginfo.h"
118
119
#if __has_feature(memory_sanitizer)
120
# include <sanitizer/msan_interface.h>
121
#endif
122
123
typedef struct _user_tick_function_entry {
124
  zend_fcall_info_cache fci_cache;
125
  zval *params;
126
  uint32_t param_count;
127
  bool calling;
128
} user_tick_function_entry;
129
130
#ifdef HAVE_PUTENV
131
typedef struct {
132
  char *putenv_string;
133
  char *previous_value;
134
  zend_string *key;
135
} putenv_entry;
136
#endif
137
138
/* some prototypes for local functions */
139
static void user_shutdown_function_dtor(zval *zv);
140
static void user_tick_function_dtor(user_tick_function_entry *tick_function_entry);
141
142
static const zend_module_dep standard_deps[] = { /* {{{ */
143
  ZEND_MOD_REQUIRED("random")
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
12
{
169
12
  putenv_entry *pe = Z_PTR_P(zv);
170
171
12
  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
12
  } else {
184
12
# ifdef HAVE_UNSETENV
185
12
    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
12
  }
203
12
#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
12
  if (zend_string_equals_literal_ci(pe->key, "TZ")) {
207
0
    tzset();
208
0
  }
209
12
#endif
210
211
12
  free(pe->putenv_string);
212
12
  zend_string_release(pe->key);
213
12
  efree(pe);
214
12
}
215
/* }}} */
216
#endif
217
218
static void basic_globals_ctor(php_basic_globals *basic_globals_p) /* {{{ */
219
16
{
220
16
  memset(basic_globals_p, 0, sizeof(php_basic_globals));
221
222
16
  basic_globals_p->umask = -1;
223
16
  basic_globals_p->url_adapt_session_ex.type = 1;
224
225
16
  zend_hash_init(&basic_globals_p->url_adapt_session_hosts_ht, 0, NULL, NULL, 1);
226
16
  zend_hash_init(&basic_globals_p->url_adapt_output_hosts_ht, 0, NULL, NULL, 1);
227
228
16
  basic_globals_p->page_uid = -1;
229
16
  basic_globals_p->page_gid = -1;
230
16
}
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
272
  if (PHP_MINIT(module)(INIT_FUNC_ARGS_PASSTHRU) != SUCCESS) {\
263
0
    return FAILURE; \
264
0
  }
265
266
#define BASIC_RINIT_SUBMODULE(module) \
267
449k
  PHP_RINIT(module)(INIT_FUNC_ARGS_PASSTHRU);
268
269
#define BASIC_MINFO_SUBMODULE(module) \
270
12
  PHP_MINFO(module)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
271
272
#define BASIC_RSHUTDOWN_SUBMODULE(module) \
273
1.34M
  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
16
{
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
16
  basic_globals_ctor(&basic_globals);
287
# ifdef PHP_WIN32
288
  php_win32_core_globals_ctor(&the_php_win32_core_globals);
289
# endif
290
16
#endif
291
292
16
  register_basic_functions_symbols(module_number);
293
294
16
  php_ce_incomplete_class = register_class___PHP_Incomplete_Class();
295
16
  php_register_incomplete_class_handlers();
296
297
16
  assertion_error_ce = register_class_AssertionError(zend_ce_error);
298
299
16
  rounding_mode_ce = register_class_RoundingMode();
300
301
16
  BASIC_MINIT_SUBMODULE(var)
302
16
  BASIC_MINIT_SUBMODULE(file)
303
16
  BASIC_MINIT_SUBMODULE(browscap)
304
16
  BASIC_MINIT_SUBMODULE(standard_filters)
305
16
  BASIC_MINIT_SUBMODULE(user_filters)
306
16
  BASIC_MINIT_SUBMODULE(password)
307
16
  BASIC_MINIT_SUBMODULE(image)
308
309
#ifdef ZTS
310
  BASIC_MINIT_SUBMODULE(localeconv)
311
#endif
312
313
#ifdef ZEND_INTRIN_SSE4_2_FUNC_PTR
314
  BASIC_MINIT_SUBMODULE(string_intrin)
315
#endif
316
317
16
#ifdef ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_PTR
318
16
  BASIC_MINIT_SUBMODULE(crc32_x86_intrin)
319
16
#endif
320
321
#if defined(ZEND_INTRIN_AVX2_FUNC_PTR) || defined(ZEND_INTRIN_SSSE3_FUNC_PTR)
322
  BASIC_MINIT_SUBMODULE(base64_intrin)
323
#endif
324
325
16
  BASIC_MINIT_SUBMODULE(crypt)
326
327
16
  BASIC_MINIT_SUBMODULE(dir)
328
16
#ifdef HAVE_SYSLOG_H
329
16
  BASIC_MINIT_SUBMODULE(syslog)
330
16
#endif
331
16
  BASIC_MINIT_SUBMODULE(array)
332
16
  BASIC_MINIT_SUBMODULE(assert)
333
16
  BASIC_MINIT_SUBMODULE(url_scanner_ex)
334
16
#ifdef PHP_CAN_SUPPORT_PROC_OPEN
335
16
  BASIC_MINIT_SUBMODULE(proc_open)
336
16
#endif
337
16
  BASIC_MINIT_SUBMODULE(exec)
338
339
16
  BASIC_MINIT_SUBMODULE(user_streams)
340
341
16
  php_register_url_stream_wrapper("php", &php_stream_php_wrapper);
342
16
  php_register_url_stream_wrapper("file", &php_plain_files_wrapper);
343
16
  php_register_url_stream_wrapper("glob", &php_glob_stream_wrapper);
344
16
  php_register_url_stream_wrapper("data", &php_stream_rfc2397_wrapper);
345
16
  php_register_url_stream_wrapper("http", &php_stream_http_wrapper);
346
16
  php_register_url_stream_wrapper("ftp", &php_stream_ftp_wrapper);
347
348
16
  return SUCCESS;
349
16
}
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
224k
{
389
224k
  memset(BG(strtok_table), 0, 256);
390
391
224k
  BG(serialize_lock) = 0;
392
224k
  memset(&BG(serialize), 0, sizeof(BG(serialize)));
393
224k
  memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
394
395
224k
  BG(strtok_string) = NULL;
396
224k
  BG(strtok_last) = NULL;
397
224k
  BG(ctype_string) = NULL;
398
224k
  BG(locale_changed) = 0;
399
224k
  BG(user_compare_fci) = empty_fcall_info;
400
224k
  BG(user_compare_fci_cache) = empty_fcall_info_cache;
401
224k
  BG(page_uid) = -1;
402
224k
  BG(page_gid) = -1;
403
224k
  BG(page_inode) = -1;
404
224k
  BG(page_mtime) = -1;
405
224k
#ifdef HAVE_PUTENV
406
224k
  zend_hash_init(&BG(putenv_ht), 1, NULL, php_putenv_destructor, 0);
407
224k
#endif
408
224k
  BG(user_shutdown_function_names) = NULL;
409
410
224k
  PHP_RINIT(filestat)(INIT_FUNC_ARGS_PASSTHRU);
411
224k
  BASIC_RINIT_SUBMODULE(dir)
412
224k
  BASIC_RINIT_SUBMODULE(url_scanner_ex)
413
414
  /* Initialize memory for last http headers */
415
224k
  ZVAL_UNDEF(&BG(last_http_headers));
416
417
  /* Setup default context */
418
224k
  FG(default_context) = NULL;
419
420
  /* Default to global wrappers only */
421
224k
  FG(stream_wrappers) = NULL;
422
423
  /* Default to global filters only */
424
224k
  FG(stream_filters) = NULL;
425
426
224k
  return SUCCESS;
427
224k
}
428
/* }}} */
429
430
PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
431
224k
{
432
224k
  if (BG(strtok_string)) {
433
41
    zend_string_release(BG(strtok_string));
434
41
    BG(strtok_string) = NULL;
435
41
  }
436
224k
#ifdef HAVE_PUTENV
437
224k
  tsrm_env_lock();
438
224k
  zend_hash_destroy(&BG(putenv_ht));
439
224k
  tsrm_env_unlock();
440
224k
#endif
441
442
224k
  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
224k
  if (BG(locale_changed)) {
449
5
    setlocale(LC_ALL, "C");
450
5
    zend_reset_lc_ctype_locale();
451
5
    zend_update_current_locale();
452
5
    if (BG(ctype_string)) {
453
0
      zend_string_release_ex(BG(ctype_string), 0);
454
0
      BG(ctype_string) = NULL;
455
0
    }
456
5
  }
457
458
  /* FG(stream_wrappers) and FG(stream_filters) are destroyed
459
   * during php_request_shutdown() */
460
461
224k
  PHP_RSHUTDOWN(filestat)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
462
224k
#ifdef HAVE_SYSLOG_H
463
224k
  BASIC_RSHUTDOWN_SUBMODULE(syslog);
464
224k
#endif
465
224k
  BASIC_RSHUTDOWN_SUBMODULE(assert)
466
224k
  BASIC_RSHUTDOWN_SUBMODULE(url_scanner_ex)
467
224k
  BASIC_RSHUTDOWN_SUBMODULE(streams)
468
#ifdef PHP_WIN32
469
  BASIC_RSHUTDOWN_SUBMODULE(win32_core_globals)
470
#endif
471
472
224k
  if (BG(user_tick_functions)) {
473
36
    zend_llist_destroy(BG(user_tick_functions));
474
36
    efree(BG(user_tick_functions));
475
36
    BG(user_tick_functions) = NULL;
476
36
  }
477
478
224k
  BASIC_RSHUTDOWN_SUBMODULE(user_filters)
479
224k
  BASIC_RSHUTDOWN_SUBMODULE(browscap)
480
481
  /* Free last http headers */
482
224k
  zval_ptr_dtor(&BG(last_http_headers));
483
484
224k
  BG(page_uid) = -1;
485
224k
  BG(page_gid) = -1;
486
224k
  return SUCCESS;
487
224k
}
488
/* }}} */
489
490
PHP_MINFO_FUNCTION(basic) /* {{{ */
491
4
{
492
4
  php_info_print_table_start();
493
4
  BASIC_MINFO_SUBMODULE(dl)
494
4
  BASIC_MINFO_SUBMODULE(mail)
495
4
  php_info_print_table_end();
496
4
  BASIC_MINFO_SUBMODULE(assert)
497
4
}
498
/* }}} */
499
500
/* {{{ Given the name of a constant this function will return the constant's associated value */
501
PHP_FUNCTION(constant)
502
119
{
503
119
  zend_string *const_name;
504
119
  zval *c;
505
119
  zend_class_entry *scope;
506
507
356
  ZEND_PARSE_PARAMETERS_START(1, 1)
508
472
    Z_PARAM_STR(const_name)
509
119
  ZEND_PARSE_PARAMETERS_END();
510
511
118
  scope = zend_get_executed_scope();
512
118
  c = zend_get_constant_ex(const_name, scope, ZEND_FETCH_CLASS_EXCEPTION);
513
118
  if (!c) {
514
17
    RETURN_THROWS();
515
17
  }
516
517
101
  ZVAL_COPY_OR_DUP(return_value, c);
518
101
  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
101
}
524
/* }}} */
525
526
/* {{{ Converts a packed inet address to a human readable IP address string */
527
PHP_FUNCTION(inet_ntop)
528
0
{
529
0
  char *address;
530
0
  size_t address_len;
531
0
  int af = AF_INET;
532
0
  char buffer[40];
533
534
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
535
0
    Z_PARAM_STRING(address, address_len)
536
0
  ZEND_PARSE_PARAMETERS_END();
537
538
0
#ifdef HAVE_IPV6
539
0
  if (address_len == 16) {
540
0
    af = AF_INET6;
541
0
  } else
542
0
#endif
543
0
  if (address_len != 4) {
544
0
    RETURN_FALSE;
545
0
  }
546
547
0
  if (!inet_ntop(af, address, buffer, sizeof(buffer))) {
548
0
    RETURN_FALSE;
549
0
  }
550
551
0
  RETURN_STRING(buffer);
552
0
}
553
/* }}} */
554
555
/* {{{ Converts a human readable IP address to a packed binary string */
556
PHP_FUNCTION(inet_pton)
557
0
{
558
0
  int ret, af = AF_INET;
559
0
  char *address;
560
0
  size_t address_len;
561
0
  char buffer[17];
562
563
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
564
0
    Z_PARAM_PATH(address, address_len)
565
0
  ZEND_PARSE_PARAMETERS_END();
566
567
0
  memset(buffer, 0, sizeof(buffer));
568
569
0
#ifdef HAVE_IPV6
570
0
  if (strchr(address, ':')) {
571
0
    af = AF_INET6;
572
0
  } else
573
0
#endif
574
0
  if (!strchr(address, '.')) {
575
0
    RETURN_FALSE;
576
0
  }
577
578
0
  ret = inet_pton(af, address, buffer);
579
580
0
  if (ret <= 0) {
581
0
    RETURN_FALSE;
582
0
  }
583
584
0
  RETURN_STRINGL(buffer, af == AF_INET ? 4 : 16);
585
0
}
586
/* }}} */
587
588
/* {{{ Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address */
589
PHP_FUNCTION(ip2long)
590
0
{
591
0
  char *addr;
592
0
  size_t addr_len;
593
0
  struct in_addr ip;
594
595
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
596
0
    Z_PARAM_PATH(addr, addr_len)
597
0
  ZEND_PARSE_PARAMETERS_END();
598
599
0
  if (addr_len == 0 || inet_pton(AF_INET, addr, &ip) != 1) {
600
0
    RETURN_FALSE;
601
0
  }
602
0
  RETURN_LONG(ntohl(ip.s_addr));
603
0
}
604
/* }}} */
605
606
/* {{{ Converts an (IPv4) Internet network address into a string in Internet standard dotted format */
607
PHP_FUNCTION(long2ip)
608
0
{
609
0
  zend_ulong ip;
610
0
  zend_long sip;
611
0
  struct in_addr myaddr;
612
0
  char str[40];
613
614
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
615
0
    Z_PARAM_LONG(sip)
616
0
  ZEND_PARSE_PARAMETERS_END();
617
618
  /* autoboxes on 32bit platforms, but that's expected */
619
0
  ip = (zend_ulong)sip;
620
621
0
  myaddr.s_addr = htonl(ip);
622
0
  const char* result = inet_ntop(AF_INET, &myaddr, str, sizeof(str));
623
0
  ZEND_ASSERT(result != NULL);
624
625
0
  RETURN_STRING(str);
626
0
}
627
/* }}} */
628
629
/********************
630
 * System Functions *
631
 ********************/
632
633
44
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
44
  tsrm_env_lock();
677
678
  /* system method returns a const */
679
44
  char *ptr = getenv(str);
680
44
  zend_string *result = NULL;
681
44
  if (ptr) {
682
0
    result = zend_string_init(ptr, strlen(ptr), 0);
683
0
  }
684
685
44
  tsrm_env_unlock();
686
44
  return result;
687
44
#endif
688
44
}
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
44
{
694
44
  char *str = NULL;
695
44
  size_t str_len;
696
44
  bool local_only = 0;
697
698
132
  ZEND_PARSE_PARAMETERS_START(0, 2)
699
132
    Z_PARAM_OPTIONAL
700
176
    Z_PARAM_STRING_OR_NULL(str, str_len)
701
132
    Z_PARAM_BOOL(local_only)
702
44
  ZEND_PARSE_PARAMETERS_END();
703
704
44
  if (!str) {
705
0
    array_init(return_value);
706
0
    php_load_environment_variables(return_value);
707
0
    return;
708
0
  }
709
710
44
  if (!local_only) {
711
    /* SAPI method returns an emalloc()'d string */
712
44
    char *ptr = sapi_getenv(str, str_len);
713
44
    if (ptr) {
714
      // TODO: avoid reallocation ???
715
0
      RETVAL_STRING(ptr);
716
0
      efree(ptr);
717
0
      return;
718
0
    }
719
44
  }
720
721
44
  zend_string *res = php_getenv(str, str_len);
722
44
  if (res) {
723
0
    RETURN_STR(res);
724
0
  }
725
44
  RETURN_FALSE;
726
44
}
727
/* }}} */
728
729
#ifdef HAVE_PUTENV
730
/* {{{ Set the value of an environment variable */
731
PHP_FUNCTION(putenv)
732
12
{
733
12
  char *setting;
734
12
  size_t setting_len;
735
12
  char *p, **env;
736
12
  putenv_entry pe;
737
#ifdef PHP_WIN32
738
  const char *value = NULL;
739
  int error_code;
740
#endif
741
742
36
  ZEND_PARSE_PARAMETERS_START(1, 1)
743
48
    Z_PARAM_STRING(setting, setting_len)
744
12
  ZEND_PARSE_PARAMETERS_END();
745
746
12
  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
12
  pe.putenv_string = zend_strndup(setting, setting_len);
752
12
  if ((p = strchr(setting, '='))) {
753
10
    pe.key = zend_string_init(setting, p - setting, 0);
754
#ifdef PHP_WIN32
755
    value = p + 1;
756
#endif
757
10
  } else {
758
2
    pe.key = zend_string_init(setting, setting_len, 0);
759
2
  }
760
761
12
  tsrm_env_lock();
762
12
  zend_hash_del(&BG(putenv_ht), pe.key);
763
764
  /* find previous value */
765
12
  pe.previous_value = NULL;
766
432
  for (env = environ; env != NULL && *env != NULL; env++) {
767
420
    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
420
  }
778
779
12
#ifdef HAVE_UNSETENV
780
12
  if (!p) { /* no '=' means we want to unset it */
781
2
    unsetenv(pe.putenv_string);
782
2
  }
783
12
  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
12
    zend_hash_add_mem(&BG(putenv_ht), pe.key, &pe, sizeof(putenv_entry));
819
12
#ifdef HAVE_TZSET
820
12
    if (zend_string_equals_literal_ci(pe.key, "TZ")) {
821
0
      tzset();
822
0
    }
823
12
#endif
824
12
    tsrm_env_unlock();
825
#ifdef PHP_WIN32
826
    free(keyw);
827
    free(valw);
828
#endif
829
12
    RETURN_TRUE;
830
12
  } 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
12
}
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
386
#define ZVAL_SET_INI_STR(zv, val) do { \
1243
386
  if (ZSTR_IS_INTERNED(val)) { \
1244
352
    ZVAL_INTERNED_STR(zv, val); \
1245
352
  } else if (ZSTR_LEN(val) == 0) { \
1246
0
    ZVAL_EMPTY_STRING(zv); \
1247
34
  } else if (ZSTR_LEN(val) == 1) { \
1248
17
    ZVAL_CHAR(zv, ZSTR_VAL(val)[0]); \
1249
17
  } else if (!(GC_FLAGS(val) & GC_PERSISTENT)) { \
1250
17
    ZVAL_NEW_STR(zv, zend_string_copy(val)); \
1251
17
  } else { \
1252
0
    ZVAL_NEW_STR(zv, zend_string_init(ZSTR_VAL(val), ZSTR_LEN(val), 0)); \
1253
0
  } \
1254
386
} 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
23
{
1333
23
  zend_string *message, *opt = NULL, *headers = NULL;
1334
23
  zend_long erropt = 0;
1335
1336
69
  ZEND_PARSE_PARAMETERS_START(1, 4)
1337
92
    Z_PARAM_STR(message)
1338
23
    Z_PARAM_OPTIONAL
1339
52
    Z_PARAM_LONG(erropt)
1340
9
    Z_PARAM_PATH_STR_OR_NULL(opt)
1341
0
    Z_PARAM_STR_OR_NULL(headers)
1342
23
  ZEND_PARSE_PARAMETERS_END();
1343
1344
23
  RETURN_BOOL(_php_error_log((int) erropt, message, opt, headers) == SUCCESS);
1345
23
}
1346
/* }}} */
1347
1348
PHPAPI zend_result _php_error_log(int opt_err, const zend_string *message, const zend_string *opt, const zend_string *headers) /* {{{ */
1349
23
{
1350
23
  php_stream *stream = NULL;
1351
23
  size_t nbytes;
1352
23
  const char *hdrs = NULL;
1353
1354
23
  switch (opt_err)
1355
23
  {
1356
2
    case 1:   /*send an email */
1357
2
      if (!opt) {
1358
2
        return FAILURE;
1359
2
      }
1360
1361
0
      hdrs = headers ? ZSTR_VAL(headers) : NULL;
1362
0
      if (!php_mail(ZSTR_VAL(opt), "PHP error_log message", ZSTR_VAL(message), hdrs, NULL)) {
1363
0
        return FAILURE;
1364
0
      }
1365
0
      break;
1366
1367
0
    case 2:   /*send to an address */
1368
0
      zend_value_error("TCP/IP option is not available for error logging");
1369
0
      return FAILURE;
1370
1371
0
    case 3:   /*save to a file */
1372
0
      stream = php_stream_open_wrapper(opt ? ZSTR_VAL(opt) : NULL, "a", REPORT_ERRORS, NULL);
1373
0
      if (!stream) {
1374
0
        return FAILURE;
1375
0
      }
1376
0
      nbytes = php_stream_write(stream, ZSTR_VAL(message), ZSTR_LEN(message));
1377
0
      php_stream_close(stream);
1378
0
      if (nbytes != ZSTR_LEN(message)) {
1379
0
        return FAILURE;
1380
0
      }
1381
0
      break;
1382
1383
0
    case 4: /* send to SAPI */
1384
0
      if (sapi_module.log_message) {
1385
0
        sapi_module.log_message(ZSTR_VAL(message), -1);
1386
0
      } else {
1387
0
        return FAILURE;
1388
0
      }
1389
0
      break;
1390
1391
21
    default:
1392
21
      php_log_err_with_severity(ZSTR_VAL(message), LOG_NOTICE);
1393
21
      break;
1394
23
  }
1395
21
  return SUCCESS;
1396
23
}
1397
/* }}} */
1398
1399
/* {{{ Get the last occurred error as associative array. Returns NULL if there hasn't been an error yet. */
1400
PHP_FUNCTION(error_get_last)
1401
62.1k
{
1402
62.1k
  ZEND_PARSE_PARAMETERS_NONE();
1403
1404
62.1k
  if (PG(last_error_message)) {
1405
62.0k
    zval tmp;
1406
62.0k
    array_init(return_value);
1407
1408
62.0k
    ZVAL_LONG(&tmp, PG(last_error_type));
1409
62.0k
    zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
1410
1411
62.0k
    ZVAL_STR_COPY(&tmp, PG(last_error_message));
1412
62.0k
    zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
1413
1414
62.0k
    ZVAL_STR_COPY(&tmp, PG(last_error_file));
1415
62.0k
    zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
1416
1417
62.0k
    ZVAL_LONG(&tmp, PG(last_error_lineno));
1418
62.0k
    zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
1419
1420
62.0k
    if (!Z_ISUNDEF(EG(last_fatal_error_backtrace))) {
1421
0
      ZVAL_COPY(&tmp, &EG(last_fatal_error_backtrace));
1422
0
      zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_TRACE), &tmp);
1423
0
    }
1424
62.0k
  }
1425
62.1k
}
1426
/* }}} */
1427
1428
/* {{{ Clear the last occurred error. */
1429
PHP_FUNCTION(error_clear_last)
1430
223
{
1431
223
  ZEND_PARSE_PARAMETERS_NONE();
1432
1433
223
  if (PG(last_error_message)) {
1434
15
    PG(last_error_type) = 0;
1435
15
    PG(last_error_lineno) = 0;
1436
1437
15
    zend_string_release(PG(last_error_message));
1438
15
    PG(last_error_message) = NULL;
1439
1440
15
    if (PG(last_error_file)) {
1441
15
      zend_string_release(PG(last_error_file));
1442
15
      PG(last_error_file) = NULL;
1443
15
    }
1444
15
  }
1445
1446
223
  zval_ptr_dtor(&EG(last_fatal_error_backtrace));
1447
223
  ZVAL_UNDEF(&EG(last_fatal_error_backtrace));
1448
223
}
1449
/* }}} */
1450
1451
/* {{{ Call a user function which is the first parameter
1452
   Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
1453
PHP_FUNCTION(call_user_func)
1454
342
{
1455
342
  zval retval;
1456
342
  zend_fcall_info fci;
1457
342
  zend_fcall_info_cache fci_cache;
1458
1459
1.02k
  ZEND_PARSE_PARAMETERS_START(1, -1)
1460
1.36k
    Z_PARAM_FUNC(fci, fci_cache)
1461
320
    Z_PARAM_VARIADIC_WITH_NAMED(fci.params, fci.param_count, fci.named_params)
1462
342
  ZEND_PARSE_PARAMETERS_END();
1463
1464
320
  fci.retval = &retval;
1465
1466
320
  if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1467
305
    if (Z_ISREF(retval)) {
1468
17
      zend_unwrap_reference(&retval);
1469
17
    }
1470
305
    ZVAL_COPY_VALUE(return_value, &retval);
1471
305
  }
1472
320
}
1473
/* }}} */
1474
1475
/* {{{ Call a user function which is the first parameter with the arguments contained in array
1476
   Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
1477
PHP_FUNCTION(call_user_func_array)
1478
75
{
1479
75
  zval retval;
1480
75
  HashTable *params;
1481
75
  zend_fcall_info fci;
1482
75
  zend_fcall_info_cache fci_cache;
1483
1484
222
  ZEND_PARSE_PARAMETERS_START(2, 2)
1485
288
    Z_PARAM_FUNC(fci, fci_cache)
1486
350
    Z_PARAM_ARRAY_HT(params)
1487
75
  ZEND_PARSE_PARAMETERS_END();
1488
1489
70
  fci.named_params = params;
1490
70
  fci.retval = &retval;
1491
1492
70
  if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1493
60
    if (Z_ISREF(retval)) {
1494
13
      zend_unwrap_reference(&retval);
1495
13
    }
1496
60
    ZVAL_COPY_VALUE(return_value, &retval);
1497
60
  }
1498
70
}
1499
/* }}} */
1500
1501
/* {{{ Call a user function which is the first parameter */
1502
PHP_FUNCTION(forward_static_call)
1503
12
{
1504
12
  zval retval;
1505
12
  zend_fcall_info fci;
1506
12
  zend_fcall_info_cache fci_cache;
1507
12
  zend_class_entry *called_scope;
1508
1509
36
  ZEND_PARSE_PARAMETERS_START(1, -1)
1510
48
    Z_PARAM_FUNC(fci, fci_cache)
1511
6
    Z_PARAM_VARIADIC('*', fci.params, fci.param_count)
1512
12
  ZEND_PARSE_PARAMETERS_END();
1513
1514
6
  if (!EX(prev_execute_data) || !EX(prev_execute_data)->func->common.scope) {
1515
0
    zend_throw_error(NULL, "Cannot call forward_static_call() when no class scope is active");
1516
0
    RETURN_THROWS();
1517
0
  }
1518
1519
6
  fci.retval = &retval;
1520
1521
6
  called_scope = zend_get_called_scope(execute_data);
1522
6
  if (called_scope && fci_cache.calling_scope &&
1523
6
    instanceof_function(called_scope, fci_cache.calling_scope)) {
1524
6
      fci_cache.called_scope = called_scope;
1525
6
  }
1526
1527
6
  if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1528
6
    if (Z_ISREF(retval)) {
1529
0
      zend_unwrap_reference(&retval);
1530
0
    }
1531
6
    ZVAL_COPY_VALUE(return_value, &retval);
1532
6
  }
1533
6
}
1534
/* }}} */
1535
1536
/* {{{ Call a static method which is the first parameter with the arguments contained in array */
1537
PHP_FUNCTION(forward_static_call_array)
1538
10
{
1539
10
  zval retval;
1540
10
  HashTable *params;
1541
10
  zend_fcall_info fci;
1542
10
  zend_fcall_info_cache fci_cache;
1543
10
  zend_class_entry *called_scope;
1544
1545
30
  ZEND_PARSE_PARAMETERS_START(2, 2)
1546
40
    Z_PARAM_FUNC(fci, fci_cache)
1547
50
    Z_PARAM_ARRAY_HT(params)
1548
10
  ZEND_PARSE_PARAMETERS_END();
1549
1550
5
  fci.retval = &retval;
1551
  /* Add positional arguments */
1552
5
  fci.named_params = params;
1553
1554
5
  called_scope = zend_get_called_scope(execute_data);
1555
5
  if (called_scope && fci_cache.calling_scope &&
1556
0
    instanceof_function(called_scope, fci_cache.calling_scope)) {
1557
0
      fci_cache.called_scope = called_scope;
1558
0
  }
1559
1560
5
  if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1561
0
    if (Z_ISREF(retval)) {
1562
0
      zend_unwrap_reference(&retval);
1563
0
    }
1564
0
    ZVAL_COPY_VALUE(return_value, &retval);
1565
0
  }
1566
5
}
1567
/* }}} */
1568
1569
void user_shutdown_function_dtor(zval *zv) /* {{{ */
1570
258
{
1571
258
  php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
1572
1573
258
  for (uint32_t i = 0; i < shutdown_function_entry->param_count; i++) {
1574
0
    zval_ptr_dtor(&shutdown_function_entry->params[i]);
1575
0
  }
1576
258
  efree(shutdown_function_entry->params);
1577
258
  zend_fcc_dtor(&shutdown_function_entry->fci_cache);
1578
258
  efree(shutdown_function_entry);
1579
258
}
1580
/* }}} */
1581
1582
void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* {{{ */
1583
54
{
1584
68
  for (uint32_t i = 0; i < tick_function_entry->param_count; i++) {
1585
14
    zval_ptr_dtor(&tick_function_entry->params[i]);
1586
14
  }
1587
54
  efree(tick_function_entry->params);
1588
54
  zend_fcc_dtor(&tick_function_entry->fci_cache);
1589
54
}
1590
/* }}} */
1591
1592
static int user_shutdown_function_call(zval *zv) /* {{{ */
1593
248
{
1594
248
  php_shutdown_function_entry *entry = Z_PTR_P(zv);
1595
1596
248
  zend_call_known_fcc(&entry->fci_cache, NULL, entry->param_count, entry->params, NULL);
1597
248
  return 0;
1598
248
}
1599
/* }}} */
1600
1601
static void user_tick_function_call(user_tick_function_entry *tick_fe) /* {{{ */
1602
344
{
1603
  /* Prevent re-entrant calls to the same user ticks function */
1604
344
  if (!tick_fe->calling) {
1605
344
    tick_fe->calling = true;
1606
344
    zend_call_known_fcc(&tick_fe->fci_cache, NULL, tick_fe->param_count, tick_fe->params, NULL);
1607
344
    tick_fe->calling = false;
1608
344
  }
1609
344
}
1610
/* }}} */
1611
1612
static void run_user_tick_functions(int tick_count, void *arg) /* {{{ */
1613
110
{
1614
110
  zend_llist_apply(BG(user_tick_functions), (llist_apply_func_t) user_tick_function_call);
1615
110
}
1616
/* }}} */
1617
1618
static int user_tick_function_compare(user_tick_function_entry * tick_fe1, user_tick_function_entry * tick_fe2) /* {{{ */
1619
0
{
1620
0
  bool is_equal = zend_fcc_equals(&tick_fe1->fci_cache, &tick_fe2->fci_cache);
1621
1622
0
  if (is_equal && tick_fe1->calling) {
1623
0
    zend_throw_error(NULL, "Registered tick function cannot be unregistered while it is being executed");
1624
0
    return false;
1625
0
  }
1626
0
  return is_equal;
1627
0
}
1628
/* }}} */
1629
1630
PHPAPI void php_call_shutdown_functions(void) /* {{{ */
1631
224k
{
1632
224k
  if (BG(user_shutdown_function_names)) {
1633
221
    zend_try {
1634
221
      zend_hash_apply(BG(user_shutdown_function_names), user_shutdown_function_call);
1635
221
    } zend_end_try();
1636
221
  }
1637
224k
}
1638
/* }}} */
1639
1640
PHPAPI void php_free_shutdown_functions(void) /* {{{ */
1641
224k
{
1642
224k
  if (BG(user_shutdown_function_names))
1643
221
    zend_try {
1644
221
      zend_hash_destroy(BG(user_shutdown_function_names));
1645
221
      FREE_HASHTABLE(BG(user_shutdown_function_names));
1646
221
      BG(user_shutdown_function_names) = NULL;
1647
221
    } zend_catch {
1648
      /* maybe shutdown method call exit, we just ignore it */
1649
0
      FREE_HASHTABLE(BG(user_shutdown_function_names));
1650
0
      BG(user_shutdown_function_names) = NULL;
1651
0
    } zend_end_try();
1652
224k
}
1653
/* }}} */
1654
1655
/* {{{ Register a user-level function to be called on request termination */
1656
PHP_FUNCTION(register_shutdown_function)
1657
263
{
1658
263
  zend_fcall_info fci;
1659
263
  php_shutdown_function_entry entry = {
1660
263
    .fci_cache = empty_fcall_info_cache,
1661
263
    .params = NULL,
1662
263
    .param_count = 0,
1663
263
  };
1664
263
  zval *params = NULL;
1665
263
  bool status;
1666
1667
263
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "F*", &fci, &entry.fci_cache, &params, &entry.param_count) == FAILURE) {
1668
5
    RETURN_THROWS();
1669
5
  }
1670
1671
258
  zend_fcc_addref(&entry.fci_cache);
1672
258
  if (entry.param_count) {
1673
0
    ZEND_ASSERT(params != NULL);
1674
0
    entry.params = (zval *) safe_emalloc(entry.param_count, sizeof(zval), 0);
1675
0
    for (uint32_t i = 0; i < entry.param_count; i++) {
1676
0
      ZVAL_COPY(&entry.params[i], &params[i]);
1677
0
    }
1678
0
  }
1679
1680
258
  status = append_user_shutdown_function(&entry);
1681
258
  ZEND_ASSERT(status);
1682
258
}
1683
/* }}} */
1684
1685
PHPAPI bool register_user_shutdown_function(const char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
1686
0
{
1687
0
  if (!BG(user_shutdown_function_names)) {
1688
0
    ALLOC_HASHTABLE(BG(user_shutdown_function_names));
1689
0
    zend_hash_init(BG(user_shutdown_function_names), 0, NULL, user_shutdown_function_dtor, 0);
1690
0
  }
1691
1692
0
  zend_hash_str_update_mem(BG(user_shutdown_function_names), function_name, function_len, shutdown_function_entry, sizeof(php_shutdown_function_entry));
1693
0
  return 1;
1694
0
}
1695
/* }}} */
1696
1697
PHPAPI bool remove_user_shutdown_function(const char *function_name, size_t function_len) /* {{{ */
1698
0
{
1699
0
  if (BG(user_shutdown_function_names)) {
1700
0
    return zend_hash_str_del(BG(user_shutdown_function_names), function_name, function_len) != FAILURE;
1701
0
  }
1702
1703
0
  return 0;
1704
0
}
1705
/* }}} */
1706
1707
PHPAPI bool append_user_shutdown_function(php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
1708
258
{
1709
258
  if (!BG(user_shutdown_function_names)) {
1710
221
    ALLOC_HASHTABLE(BG(user_shutdown_function_names));
1711
221
    zend_hash_init(BG(user_shutdown_function_names), 0, NULL, user_shutdown_function_dtor, 0);
1712
221
  }
1713
1714
258
  return zend_hash_next_index_insert_mem(BG(user_shutdown_function_names), shutdown_function_entry, sizeof(php_shutdown_function_entry)) != NULL;
1715
258
}
1716
/* }}} */
1717
1718
ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini) /* {{{ */
1719
32.9k
{
1720
32.9k
  syntax_highlighter_ini->highlight_comment = zend_ini_string_literal("highlight.comment");
1721
32.9k
  syntax_highlighter_ini->highlight_default = zend_ini_string_literal("highlight.default");
1722
32.9k
  syntax_highlighter_ini->highlight_html    = zend_ini_string_literal("highlight.html");
1723
32.9k
  syntax_highlighter_ini->highlight_keyword = zend_ini_string_literal("highlight.keyword");
1724
32.9k
  syntax_highlighter_ini->highlight_string  = zend_ini_string_literal("highlight.string");
1725
32.9k
}
1726
/* }}} */
1727
1728
/* {{{ Syntax highlight a source file */
1729
PHP_FUNCTION(highlight_file)
1730
0
{
1731
0
  char *filename;
1732
0
  size_t filename_len;
1733
0
  int ret;
1734
0
  zend_syntax_highlighter_ini syntax_highlighter_ini;
1735
0
  bool i = 0;
1736
1737
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
1738
0
    Z_PARAM_PATH(filename, filename_len)
1739
0
    Z_PARAM_OPTIONAL
1740
0
    Z_PARAM_BOOL(i)
1741
0
  ZEND_PARSE_PARAMETERS_END();
1742
1743
0
  if (php_check_open_basedir(filename)) {
1744
0
    RETURN_FALSE;
1745
0
  }
1746
1747
0
  if (i) {
1748
0
    if (UNEXPECTED(php_output_start_default() != SUCCESS)) {
1749
0
      zend_throw_error(NULL, "Unable to start output handler");
1750
0
      RETURN_THROWS();
1751
0
    }
1752
0
  }
1753
1754
0
  php_get_highlight_struct(&syntax_highlighter_ini);
1755
1756
0
  ret = highlight_file(filename, &syntax_highlighter_ini);
1757
1758
0
  if (ret == FAILURE) {
1759
0
    if (i) {
1760
0
      php_output_end();
1761
0
    }
1762
0
    RETURN_FALSE;
1763
0
  }
1764
1765
0
  if (i) {
1766
0
    php_output_get_contents(return_value);
1767
0
    php_output_discard();
1768
0
    ZEND_ASSERT(Z_TYPE_P(return_value) == IS_STRING);
1769
0
  } else {
1770
0
    RETURN_TRUE;
1771
0
  }
1772
0
}
1773
/* }}} */
1774
1775
/* {{{ Return source with stripped comments and whitespace */
1776
PHP_FUNCTION(php_strip_whitespace)
1777
0
{
1778
0
  zend_string *filename;
1779
0
  zend_lex_state original_lex_state;
1780
0
  zend_file_handle file_handle;
1781
1782
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1783
0
    Z_PARAM_PATH_STR(filename)
1784
0
  ZEND_PARSE_PARAMETERS_END();
1785
1786
0
  if (UNEXPECTED(php_output_start_default() != SUCCESS)) {
1787
0
    zend_throw_error(NULL, "Unable to start output handler");
1788
0
    RETURN_THROWS();
1789
0
  }
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
32.9k
{
1813
32.9k
  zend_string *str;
1814
32.9k
  zend_syntax_highlighter_ini syntax_highlighter_ini;
1815
32.9k
  char *hicompiled_string_description;
1816
32.9k
  bool i = 0;
1817
32.9k
  int old_error_reporting = EG(error_reporting);
1818
1819
98.9k
  ZEND_PARSE_PARAMETERS_START(1, 2)
1820
131k
    Z_PARAM_STR(str)
1821
32.9k
    Z_PARAM_OPTIONAL
1822
67.8k
    Z_PARAM_BOOL(i)
1823
32.9k
  ZEND_PARSE_PARAMETERS_END();
1824
1825
32.9k
  if (i) {
1826
898
    if (UNEXPECTED(php_output_start_default() != SUCCESS)) {
1827
0
      zend_throw_error(NULL, "Unable to start output handler");
1828
0
      RETURN_THROWS();
1829
0
    }
1830
898
  }
1831
1832
32.9k
  EG(error_reporting) = E_ERROR;
1833
1834
32.9k
  php_get_highlight_struct(&syntax_highlighter_ini);
1835
1836
32.9k
  hicompiled_string_description = zend_make_compiled_string_description("highlighted code");
1837
1838
32.9k
  highlight_string(str, &syntax_highlighter_ini, hicompiled_string_description);
1839
32.9k
  efree(hicompiled_string_description);
1840
1841
32.9k
  EG(error_reporting) = old_error_reporting;
1842
1843
32.9k
  if (i) {
1844
898
    php_output_get_contents(return_value);
1845
898
    php_output_discard();
1846
898
    ZEND_ASSERT(Z_TYPE_P(return_value) == IS_STRING);
1847
32.0k
  } else {
1848
    // TODO Make this function void?
1849
32.0k
    RETURN_TRUE;
1850
32.0k
  }
1851
32.9k
}
1852
/* }}} */
1853
1854
/* {{{ Get interpreted size from the ini shorthand syntax */
1855
PHP_FUNCTION(ini_parse_quantity)
1856
359
{
1857
359
  zend_string *shorthand;
1858
359
  zend_string *errstr;
1859
1860
1.07k
  ZEND_PARSE_PARAMETERS_START(1, 1)
1861
1.43k
    Z_PARAM_STR(shorthand)
1862
359
  ZEND_PARSE_PARAMETERS_END();
1863
1864
358
  RETVAL_LONG(zend_ini_parse_quantity(shorthand, &errstr));
1865
1866
358
  if (errstr) {
1867
258
    zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
1868
258
    zend_string_release(errstr);
1869
258
  }
1870
358
}
1871
/* }}} */
1872
1873
/* {{{ Get a configuration option */
1874
PHP_FUNCTION(ini_get)
1875
102
{
1876
102
  zend_string *varname, *val;
1877
1878
306
  ZEND_PARSE_PARAMETERS_START(1, 1)
1879
408
    Z_PARAM_STR(varname)
1880
102
  ZEND_PARSE_PARAMETERS_END();
1881
1882
102
  val = zend_ini_get_value(varname);
1883
1884
102
  if (!val) {
1885
36
    RETURN_FALSE;
1886
36
  }
1887
1888
66
  ZVAL_SET_INI_STR(return_value, val);
1889
66
}
1890
/* }}} */
1891
1892
/* {{{ Get all configuration options */
1893
PHP_FUNCTION(ini_get_all)
1894
0
{
1895
0
  zend_string *extname = NULL;
1896
0
  size_t module_number = 0;
1897
0
  zend_module_entry *module;
1898
0
  bool details = 1;
1899
0
  zend_string *key;
1900
0
  zend_ini_entry *ini_entry;
1901
1902
1903
0
  ZEND_PARSE_PARAMETERS_START(0, 2)
1904
0
    Z_PARAM_OPTIONAL
1905
0
    Z_PARAM_STR_OR_NULL(extname)
1906
0
    Z_PARAM_BOOL(details)
1907
0
  ZEND_PARSE_PARAMETERS_END();
1908
1909
0
  zend_ini_sort_entries();
1910
1911
0
  if (extname) {
1912
0
    if ((module = zend_hash_find_ptr(&module_registry, extname)) == NULL) {
1913
0
      php_error_docref(NULL, E_WARNING, "Extension \"%s\" cannot be found", ZSTR_VAL(extname));
1914
0
      RETURN_FALSE;
1915
0
    }
1916
0
    module_number = module->module_number;
1917
0
  }
1918
1919
0
  array_init(return_value);
1920
0
  ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(ini_directives), key, ini_entry) {
1921
0
    zval option;
1922
1923
0
    if (module_number != 0 && ini_entry->module_number != module_number) {
1924
0
      continue;
1925
0
    }
1926
1927
0
    if (key == NULL || ZSTR_VAL(key)[0] != 0) {
1928
0
      if (details) {
1929
0
        array_init(&option);
1930
1931
0
        if (ini_entry->orig_value) {
1932
0
          add_assoc_str(&option, "global_value", zend_string_copy(ini_entry->orig_value));
1933
0
        } else if (ini_entry->value) {
1934
0
          add_assoc_str(&option, "global_value", zend_string_copy(ini_entry->value));
1935
0
        } else {
1936
0
          add_assoc_null(&option, "global_value");
1937
0
        }
1938
1939
0
        if (ini_entry->value) {
1940
0
          add_assoc_str(&option, "local_value", zend_string_copy(ini_entry->value));
1941
0
        } else {
1942
0
          add_assoc_null(&option, "local_value");
1943
0
        }
1944
1945
0
        add_assoc_long(&option, "access", ini_entry->modifiable);
1946
1947
0
        zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &option);
1948
0
      } else {
1949
0
        if (ini_entry->value) {
1950
0
          zval zv;
1951
1952
0
          ZVAL_STR_COPY(&zv, ini_entry->value);
1953
0
          zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &zv);
1954
0
        } else {
1955
0
          zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &EG(uninitialized_zval));
1956
0
        }
1957
0
      }
1958
0
    }
1959
0
  } ZEND_HASH_FOREACH_END();
1960
0
}
1961
/* }}} */
1962
1963
/* {{{ Set a configuration option, returns false on error and the old value of the configuration option on success */
1964
PHP_FUNCTION(ini_set)
1965
878
{
1966
878
  zend_string *varname;
1967
878
  zval *new_value;
1968
878
  zend_string *val;
1969
1970
2.62k
  ZEND_PARSE_PARAMETERS_START(2, 2)
1971
3.46k
    Z_PARAM_STR(varname)
1972
4.33k
    Z_PARAM_ZVAL(new_value)
1973
4.33k
  ZEND_PARSE_PARAMETERS_END();
1974
1975
867
  if (Z_TYPE_P(new_value) > IS_STRING) {
1976
0
    zend_argument_type_error(2, "must be of type string|int|float|bool|null");
1977
0
    RETURN_THROWS();
1978
0
  }
1979
1980
867
  val = zend_ini_get_value(varname);
1981
1982
867
  if (val) {
1983
320
    ZVAL_SET_INI_STR(return_value, val);
1984
547
  } else {
1985
547
    RETVAL_FALSE;
1986
547
  }
1987
1988
867
  zend_string *new_value_tmp_str;
1989
867
  zend_string *new_value_str = zval_get_tmp_string(new_value, &new_value_tmp_str);
1990
1991
  /* open basedir check */
1992
867
  if (PG(open_basedir)) {
1993
867
    if (
1994
867
      zend_string_equals_literal(varname, "java.class.path")
1995
867
      || zend_string_equals_literal(varname, "java.home")
1996
867
      || zend_string_equals_literal(varname, "java.library.path")
1997
867
      || zend_string_equals_literal(varname, "vpopmail.directory")
1998
867
    ) {
1999
0
      if (php_check_open_basedir(ZSTR_VAL(new_value_str))) {
2000
0
        zval_ptr_dtor_str(return_value);
2001
0
        zend_tmp_string_release(new_value_tmp_str);
2002
0
        RETURN_FALSE;
2003
0
      }
2004
0
    }
2005
867
  }
2006
2007
867
  if (zend_alter_ini_entry_ex(varname, new_value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) {
2008
645
    zval_ptr_dtor_str(return_value);
2009
645
    RETVAL_FALSE;
2010
645
  }
2011
867
  zend_tmp_string_release(new_value_tmp_str);
2012
867
}
2013
/* }}} */
2014
2015
/* {{{ Restore the value of a configuration option specified by varname */
2016
PHP_FUNCTION(ini_restore)
2017
0
{
2018
0
  zend_string *varname;
2019
2020
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2021
0
    Z_PARAM_STR(varname)
2022
0
  ZEND_PARSE_PARAMETERS_END();
2023
2024
0
  zend_restore_ini_entry(varname, PHP_INI_STAGE_RUNTIME);
2025
0
}
2026
/* }}} */
2027
2028
/* {{{ Sets the include_path configuration option */
2029
PHP_FUNCTION(set_include_path)
2030
41
{
2031
41
  zend_string *new_value;
2032
41
  zend_string *key;
2033
2034
123
  ZEND_PARSE_PARAMETERS_START(1, 1)
2035
164
    Z_PARAM_PATH_STR(new_value)
2036
41
  ZEND_PARSE_PARAMETERS_END();
2037
2038
38
  zend_string *old_value = zend_ini_str_literal("include_path");
2039
  /* copy to return here, because alter might free it! */
2040
38
  if (old_value) {
2041
38
    RETVAL_STR_COPY(old_value);
2042
38
  } else {
2043
0
    RETVAL_FALSE;
2044
0
  }
2045
2046
38
  key = ZSTR_INIT_LITERAL("include_path", 0);
2047
38
  if (zend_alter_ini_entry_ex(key, new_value, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) {
2048
0
    zend_string_release_ex(key, 0);
2049
0
    zval_ptr_dtor_str(return_value);
2050
0
    RETURN_FALSE;
2051
0
  }
2052
38
  zend_string_release_ex(key, 0);
2053
38
}
2054
/* }}} */
2055
2056
/* {{{ Get the current include_path configuration option */
2057
PHP_FUNCTION(get_include_path)
2058
0
{
2059
0
  ZEND_PARSE_PARAMETERS_NONE();
2060
2061
0
  zend_string *str = zend_ini_str_literal("include_path");
2062
2063
0
  if (str == NULL) {
2064
0
    RETURN_FALSE;
2065
0
  }
2066
2067
0
  RETURN_STR_COPY(str);
2068
0
}
2069
/* }}} */
2070
2071
/* {{{ Prints out or returns information about the specified variable */
2072
PHP_FUNCTION(print_r)
2073
2.06k
{
2074
2.06k
  zval *var;
2075
2.06k
  bool do_return = 0;
2076
2077
6.19k
  ZEND_PARSE_PARAMETERS_START(1, 2)
2078
8.26k
    Z_PARAM_ZVAL(var)
2079
8.26k
    Z_PARAM_OPTIONAL
2080
8.26k
    Z_PARAM_BOOL(do_return)
2081
2.06k
  ZEND_PARSE_PARAMETERS_END();
2082
2083
2.06k
  if (do_return) {
2084
29
    RETURN_STR(zend_print_zval_r_to_str(var, 0));
2085
2.03k
  } else {
2086
2.03k
    zend_print_zval_r(var, 0);
2087
2.03k
    RETURN_TRUE;
2088
2.03k
  }
2089
2.06k
}
2090
/* }}} */
2091
2092
/* {{{ Returns true if client disconnected */
2093
PHP_FUNCTION(connection_aborted)
2094
0
{
2095
0
  ZEND_PARSE_PARAMETERS_NONE();
2096
2097
0
  RETURN_LONG(PG(connection_status) & PHP_CONNECTION_ABORTED);
2098
0
}
2099
/* }}} */
2100
2101
/* {{{ Returns the connection status bitfield */
2102
PHP_FUNCTION(connection_status)
2103
0
{
2104
0
  ZEND_PARSE_PARAMETERS_NONE();
2105
2106
0
  RETURN_LONG(PG(connection_status));
2107
0
}
2108
/* }}} */
2109
2110
/* {{{ Set whether we want to ignore a user abort event or not */
2111
PHP_FUNCTION(ignore_user_abort)
2112
0
{
2113
0
  bool arg = 0;
2114
0
  bool arg_is_null = 1;
2115
0
  int old_setting;
2116
2117
0
  ZEND_PARSE_PARAMETERS_START(0, 1)
2118
0
    Z_PARAM_OPTIONAL
2119
0
    Z_PARAM_BOOL_OR_NULL(arg, arg_is_null)
2120
0
  ZEND_PARSE_PARAMETERS_END();
2121
2122
0
  old_setting = (unsigned short)PG(ignore_user_abort);
2123
2124
0
  if (!arg_is_null) {
2125
0
    zend_string *key = ZSTR_INIT_LITERAL("ignore_user_abort", 0);
2126
0
    zend_alter_ini_entry_chars(key, arg ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
2127
0
    zend_string_release_ex(key, 0);
2128
0
  }
2129
2130
0
  RETURN_LONG(old_setting);
2131
0
}
2132
/* }}} */
2133
2134
#ifdef HAVE_GETSERVBYNAME
2135
/* {{{ Returns port associated with service. Protocol must be "tcp" or "udp" */
2136
PHP_FUNCTION(getservbyname)
2137
0
{
2138
0
  zend_string *name;
2139
0
  char *proto;
2140
0
  size_t proto_len;
2141
0
  struct servent *serv;
2142
2143
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
2144
0
    Z_PARAM_PATH_STR(name)
2145
0
    Z_PARAM_PATH(proto, proto_len)
2146
0
  ZEND_PARSE_PARAMETERS_END();
2147
2148
2149
/* empty string behaves like NULL on windows implementation of
2150
   getservbyname. Let be portable instead. */
2151
#ifdef PHP_WIN32
2152
  if (proto_len == 0) {
2153
    RETURN_FALSE;
2154
  }
2155
#endif
2156
2157
0
  serv = getservbyname(ZSTR_VAL(name), proto);
2158
2159
#ifdef _AIX
2160
  /*
2161
        On AIX, imap is only known as imap2 in /etc/services, while on Linux imap is an alias for imap2.
2162
        If a request for imap gives no result, we try again with imap2.
2163
        */
2164
  if (serv == NULL && zend_string_equals_literal(name, "imap")) {
2165
    serv = getservbyname("imap2", proto);
2166
  }
2167
#endif
2168
0
  if (serv == NULL) {
2169
0
    RETURN_FALSE;
2170
0
  }
2171
2172
0
  RETURN_LONG(ntohs(serv->s_port));
2173
0
}
2174
/* }}} */
2175
#endif
2176
2177
#ifdef HAVE_GETSERVBYPORT
2178
/* {{{ Returns service name associated with port. Protocol must be "tcp" or "udp" */
2179
PHP_FUNCTION(getservbyport)
2180
0
{
2181
0
  char *proto;
2182
0
  size_t proto_len;
2183
0
  zend_long port;
2184
0
  struct servent *serv;
2185
2186
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
2187
0
    Z_PARAM_LONG(port)
2188
0
    Z_PARAM_PATH(proto, proto_len)
2189
0
  ZEND_PARSE_PARAMETERS_END();
2190
2191
0
  serv = getservbyport(htons((unsigned short) port), proto);
2192
2193
0
  if (serv == NULL) {
2194
0
    RETURN_FALSE;
2195
0
  }
2196
2197
  /* MSAN false positive, getservbyport() is not properly intercepted. */
2198
#if __has_feature(memory_sanitizer)
2199
  __msan_unpoison_string(serv->s_name);
2200
#endif
2201
0
  RETURN_STRING(serv->s_name);
2202
0
}
2203
/* }}} */
2204
#endif
2205
2206
#ifdef HAVE_GETPROTOBYNAME
2207
/* {{{ Returns protocol number associated with name as per /etc/protocols */
2208
PHP_FUNCTION(getprotobyname)
2209
0
{
2210
0
  char *name;
2211
0
  size_t name_len;
2212
0
  struct protoent *ent;
2213
2214
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2215
0
    Z_PARAM_PATH(name, name_len)
2216
0
  ZEND_PARSE_PARAMETERS_END();
2217
2218
0
  ent = getprotobyname(name);
2219
2220
0
  if (ent == NULL) {
2221
0
    RETURN_FALSE;
2222
0
  }
2223
2224
0
  RETURN_LONG(ent->p_proto);
2225
0
}
2226
/* }}} */
2227
#endif
2228
2229
#ifdef HAVE_GETPROTOBYNUMBER
2230
/* {{{ Returns protocol name associated with protocol number proto */
2231
PHP_FUNCTION(getprotobynumber)
2232
0
{
2233
0
  zend_long proto;
2234
0
  struct protoent *ent;
2235
2236
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2237
0
    Z_PARAM_LONG(proto)
2238
0
  ZEND_PARSE_PARAMETERS_END();
2239
2240
0
  ent = getprotobynumber((int)proto);
2241
2242
0
  if (ent == NULL) {
2243
0
    RETURN_FALSE;
2244
0
  }
2245
2246
0
  RETURN_STRING(ent->p_name);
2247
0
}
2248
/* }}} */
2249
#endif
2250
2251
/* {{{ Registers a tick callback function */
2252
PHP_FUNCTION(register_tick_function)
2253
54
{
2254
54
  user_tick_function_entry tick_fe = {
2255
54
    .fci_cache = empty_fcall_info_cache,
2256
54
    .params = NULL,
2257
54
    .param_count = 0,
2258
54
    .calling = false,
2259
54
  };
2260
54
  zend_fcall_info fci;
2261
54
  zval *params = NULL;
2262
2263
54
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "F*", &fci, &tick_fe.fci_cache, &params, &tick_fe.param_count) == FAILURE) {
2264
0
    RETURN_THROWS();
2265
0
  }
2266
2267
54
  zend_fcc_addref(&tick_fe.fci_cache);
2268
54
  if (tick_fe.param_count) {
2269
7
    ZEND_ASSERT(params != NULL);
2270
7
    tick_fe.params = (zval *) safe_emalloc(tick_fe.param_count, sizeof(zval), 0);
2271
21
    for (uint32_t i = 0; i < tick_fe.param_count; i++) {
2272
14
      ZVAL_COPY(&tick_fe.params[i], &params[i]);
2273
14
    }
2274
7
  }
2275
2276
54
  if (!BG(user_tick_functions)) {
2277
36
    BG(user_tick_functions) = (zend_llist *) emalloc(sizeof(zend_llist));
2278
36
    zend_llist_init(BG(user_tick_functions),
2279
36
            sizeof(user_tick_function_entry),
2280
36
            (llist_dtor_func_t) user_tick_function_dtor, 0);
2281
36
    php_add_tick_function(run_user_tick_functions, NULL);
2282
36
  }
2283
2284
54
  zend_llist_add_element(BG(user_tick_functions), &tick_fe);
2285
2286
54
  RETURN_TRUE;
2287
54
}
2288
/* }}} */
2289
2290
/* {{{ Unregisters a tick callback function */
2291
PHP_FUNCTION(unregister_tick_function)
2292
0
{
2293
0
  user_tick_function_entry tick_fe = {
2294
0
    .fci_cache = empty_fcall_info_cache,
2295
0
    .params = NULL,
2296
0
    .param_count = 0,
2297
0
    .calling = false,
2298
0
  };
2299
0
  zend_fcall_info fci;
2300
2301
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2302
0
    Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, tick_fe.fci_cache)
2303
0
  ZEND_PARSE_PARAMETERS_END();
2304
2305
0
  if (BG(user_tick_functions)) {
2306
0
    zend_llist_del_element(BG(user_tick_functions), &tick_fe, (int (*)(void *, void *)) user_tick_function_compare);
2307
0
  }
2308
2309
  /* Free potential trampoline */
2310
0
  zend_release_fcall_info_cache(&tick_fe.fci_cache);
2311
0
}
2312
/* }}} */
2313
2314
/* {{{ Check if file was created by rfc1867 upload */
2315
PHP_FUNCTION(is_uploaded_file)
2316
0
{
2317
0
  zend_string *path;
2318
2319
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
2320
0
    Z_PARAM_PATH_STR(path)
2321
0
  ZEND_PARSE_PARAMETERS_END();
2322
2323
0
  if (!SG(rfc1867_uploaded_files)) {
2324
0
    RETURN_FALSE;
2325
0
  }
2326
2327
0
  RETURN_BOOL(zend_hash_exists(SG(rfc1867_uploaded_files), path));
2328
0
}
2329
/* }}} */
2330
2331
/* {{{ Move a file if and only if it was created by an upload */
2332
PHP_FUNCTION(move_uploaded_file)
2333
0
{
2334
0
  zend_string *path, *new_path;
2335
0
  bool successful = 0;
2336
2337
0
#ifndef PHP_WIN32
2338
0
  int oldmask; int ret;
2339
0
#endif
2340
2341
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
2342
0
    Z_PARAM_PATH_STR(path)
2343
0
    Z_PARAM_PATH_STR(new_path)
2344
0
  ZEND_PARSE_PARAMETERS_END();
2345
2346
0
  if (!SG(rfc1867_uploaded_files)) {
2347
0
    RETURN_FALSE;
2348
0
  }
2349
2350
0
  if (!zend_hash_exists(SG(rfc1867_uploaded_files), path)) {
2351
0
    RETURN_FALSE;
2352
0
  }
2353
2354
0
  if (php_check_open_basedir(ZSTR_VAL(new_path))) {
2355
0
    RETURN_FALSE;
2356
0
  }
2357
2358
0
  if (VCWD_RENAME(ZSTR_VAL(path), ZSTR_VAL(new_path)) == 0) {
2359
0
    successful = 1;
2360
0
#ifndef PHP_WIN32
2361
0
    oldmask = umask(077);
2362
0
    umask(oldmask);
2363
2364
0
    ret = VCWD_CHMOD(ZSTR_VAL(new_path), 0666 & ~oldmask);
2365
2366
0
    if (ret == -1) {
2367
0
      php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
2368
0
    }
2369
0
#endif
2370
0
  } else if (php_copy_file_ex(ZSTR_VAL(path), ZSTR_VAL(new_path), STREAM_DISABLE_OPEN_BASEDIR) == SUCCESS) {
2371
0
    VCWD_UNLINK(ZSTR_VAL(path));
2372
0
    successful = 1;
2373
0
  }
2374
2375
0
  if (successful) {
2376
0
    zend_hash_del(SG(rfc1867_uploaded_files), path);
2377
0
  } else {
2378
0
    php_error_docref(NULL, E_WARNING, "Unable to move \"%s\" to \"%s\"", ZSTR_VAL(path), ZSTR_VAL(new_path));
2379
0
  }
2380
2381
0
  RETURN_BOOL(successful);
2382
0
}
2383
/* }}} */
2384
2385
/* {{{ php_simple_ini_parser_cb */
2386
static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr)
2387
514k
{
2388
514k
  switch (callback_type) {
2389
2390
494k
    case ZEND_INI_PARSER_ENTRY:
2391
494k
      if (!arg2) {
2392
        /* bare string - nothing to do */
2393
248k
        break;
2394
248k
      }
2395
246k
      Z_TRY_ADDREF_P(arg2);
2396
246k
      zend_symtable_update(Z_ARRVAL_P(arr), Z_STR_P(arg1), arg2);
2397
246k
      break;
2398
2399
4.57k
    case ZEND_INI_PARSER_POP_ENTRY:
2400
4.57k
    {
2401
4.57k
      zval hash, *find_hash;
2402
2403
4.57k
      if (!arg2) {
2404
        /* bare string - nothing to do */
2405
0
        break;
2406
0
      }
2407
2408
      /* entry in the form x[a]=b where x might need to be an array index */
2409
4.57k
      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) {
2410
0
        zend_ulong key = (zend_ulong) ZEND_STRTOUL(Z_STRVAL_P(arg1), NULL, 0);
2411
0
        if ((find_hash = zend_hash_index_find(Z_ARRVAL_P(arr), key)) == NULL) {
2412
0
          array_init(&hash);
2413
0
          find_hash = zend_hash_index_add_new(Z_ARRVAL_P(arr), key, &hash);
2414
0
        }
2415
4.57k
      } else {
2416
4.57k
        if ((find_hash = zend_hash_find(Z_ARRVAL_P(arr), Z_STR_P(arg1))) == NULL) {
2417
831
          array_init(&hash);
2418
831
          find_hash = zend_hash_add_new(Z_ARRVAL_P(arr), Z_STR_P(arg1), &hash);
2419
831
        }
2420
4.57k
      }
2421
2422
4.57k
      if (Z_TYPE_P(find_hash) != IS_ARRAY) {
2423
0
        zval_ptr_dtor_nogc(find_hash);
2424
0
        array_init(find_hash);
2425
0
      }
2426
2427
4.57k
      if (!arg3 || (Z_TYPE_P(arg3) == IS_STRING && Z_STRLEN_P(arg3) == 0)) {
2428
149
        Z_TRY_ADDREF_P(arg2);
2429
149
        add_next_index_zval(find_hash, arg2);
2430
4.42k
      } else {
2431
4.42k
        array_set_zval_key(Z_ARRVAL_P(find_hash), arg3, arg2);
2432
4.42k
      }
2433
4.57k
    }
2434
0
    break;
2435
2436
15.5k
    case ZEND_INI_PARSER_SECTION:
2437
15.5k
      break;
2438
514k
  }
2439
514k
}
2440
/* }}} */
2441
2442
/* {{{ php_ini_parser_cb_with_sections */
2443
static void php_ini_parser_cb_with_sections(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr)
2444
5.54k
{
2445
5.54k
  if (callback_type == ZEND_INI_PARSER_SECTION) {
2446
309
    array_init(&BG(active_ini_file_section));
2447
309
    zend_symtable_update(Z_ARRVAL_P(arr), Z_STR_P(arg1), &BG(active_ini_file_section));
2448
5.23k
  } else if (arg2) {
2449
2.89k
    zval *active_arr;
2450
2451
2.89k
    if (Z_TYPE(BG(active_ini_file_section)) != IS_UNDEF) {
2452
885
      active_arr = &BG(active_ini_file_section);
2453
2.00k
    } else {
2454
2.00k
      active_arr = arr;
2455
2.00k
    }
2456
2457
2.89k
    php_simple_ini_parser_cb(arg1, arg2, arg3, callback_type, active_arr);
2458
2.89k
  }
2459
5.54k
}
2460
/* }}} */
2461
2462
/* {{{ Parse configuration file */
2463
PHP_FUNCTION(parse_ini_file)
2464
12
{
2465
12
  zend_string *filename = NULL;
2466
12
  bool process_sections = 0;
2467
12
  zend_long scanner_mode = ZEND_INI_SCANNER_NORMAL;
2468
12
  zend_file_handle fh;
2469
12
  zend_ini_parser_cb_t ini_parser_cb;
2470
2471
36
  ZEND_PARSE_PARAMETERS_START(1, 3)
2472
48
    Z_PARAM_PATH_STR(filename)
2473
12
    Z_PARAM_OPTIONAL
2474
48
    Z_PARAM_BOOL(process_sections)
2475
58
    Z_PARAM_LONG(scanner_mode)
2476
12
  ZEND_PARSE_PARAMETERS_END();
2477
2478
9
  if (ZSTR_LEN(filename) == 0) {
2479
1
    zend_argument_must_not_be_empty_error(1);
2480
1
    RETURN_THROWS();
2481
1
  }
2482
2483
  /* Set callback function */
2484
8
  if (process_sections) {
2485
4
    ZVAL_UNDEF(&BG(active_ini_file_section));
2486
4
    ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections;
2487
4
  } else {
2488
4
    ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb;
2489
4
  }
2490
2491
  /* Setup filehandle */
2492
8
  zend_stream_init_filename_ex(&fh, filename);
2493
2494
8
  array_init(return_value);
2495
8
  if (zend_parse_ini_file(&fh, 0, (int)scanner_mode, ini_parser_cb, return_value) == FAILURE) {
2496
8
    zend_array_destroy(Z_ARR_P(return_value));
2497
8
    RETVAL_FALSE;
2498
8
  }
2499
8
  zend_destroy_file_handle(&fh);
2500
8
}
2501
/* }}} */
2502
2503
/* {{{ Parse configuration string */
2504
PHP_FUNCTION(parse_ini_string)
2505
72.6k
{
2506
72.6k
  char *string = NULL, *str = NULL;
2507
72.6k
  size_t str_len = 0;
2508
72.6k
  bool process_sections = 0;
2509
72.6k
  zend_long scanner_mode = ZEND_INI_SCANNER_NORMAL;
2510
72.6k
  zend_ini_parser_cb_t ini_parser_cb;
2511
2512
217k
  ZEND_PARSE_PARAMETERS_START(1, 3)
2513
290k
    Z_PARAM_STRING(str, str_len)
2514
72.6k
    Z_PARAM_OPTIONAL
2515
149k
    Z_PARAM_BOOL(process_sections)
2516
9.24k
    Z_PARAM_LONG(scanner_mode)
2517
72.6k
  ZEND_PARSE_PARAMETERS_END();
2518
2519
72.6k
  if (INT_MAX - str_len < ZEND_MMAP_AHEAD) {
2520
0
    RETVAL_FALSE;
2521
0
  }
2522
2523
  /* Set callback function */
2524
72.6k
  if (process_sections) {
2525
1.58k
    ZVAL_UNDEF(&BG(active_ini_file_section));
2526
1.58k
    ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections;
2527
71.0k
  } else {
2528
71.0k
    ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb;
2529
71.0k
  }
2530
2531
  /* Setup string */
2532
72.6k
  string = (char *) emalloc(str_len + ZEND_MMAP_AHEAD);
2533
72.6k
  memcpy(string, str, str_len);
2534
72.6k
  memset(string + str_len, 0, ZEND_MMAP_AHEAD);
2535
2536
72.6k
  array_init(return_value);
2537
72.6k
  if (zend_parse_ini_string(string, 0, (int)scanner_mode, ini_parser_cb, return_value) == FAILURE) {
2538
50.2k
    zend_array_destroy(Z_ARR_P(return_value));
2539
50.2k
    RETVAL_FALSE;
2540
50.2k
  }
2541
72.6k
  efree(string);
2542
72.6k
}
2543
/* }}} */
2544
2545
#if ZEND_DEBUG
2546
/* This function returns an array of ALL valid ini options with values and
2547
 *  is not the same as ini_get_all() which returns only registered ini options. Only useful for devs to debug php.ini scanner/parser! */
2548
PHP_FUNCTION(config_get_hash) /* {{{ */
2549
0
{
2550
0
  ZEND_PARSE_PARAMETERS_NONE();
2551
2552
0
  HashTable *hash = php_ini_get_configuration_hash();
2553
2554
0
  array_init(return_value);
2555
0
  add_config_entries(hash, return_value);
2556
0
}
2557
/* }}} */
2558
#endif
2559
2560
#ifdef HAVE_GETLOADAVG
2561
/* {{{ */
2562
PHP_FUNCTION(sys_getloadavg)
2563
0
{
2564
0
  double load[3];
2565
2566
0
  ZEND_PARSE_PARAMETERS_NONE();
2567
2568
0
  if (getloadavg(load, 3) == -1) {
2569
0
    RETURN_FALSE;
2570
0
  } else {
2571
0
    array_init(return_value);
2572
0
    add_index_double(return_value, 0, load[0]);
2573
0
    add_index_double(return_value, 1, load[1]);
2574
0
    add_index_double(return_value, 2, load[2]);
2575
0
  }
2576
0
}
2577
/* }}} */
2578
#endif