Coverage Report

Created: 2025-06-13 06:43

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