Coverage Report

Created: 2026-06-02 06:39

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