Coverage Report

Created: 2026-10-28 06:20

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