Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7ca4300

Browse files
committed
Merge branch 'PHP-8.3'
2 parents fc14f17 + 049082e commit 7ca4300

File tree

11 files changed

+330
-46
lines changed

11 files changed

+330
-46
lines changed

‎NEWS‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ PHP NEWS
195195
. Added multicast group support for ipv4 on FreeBSD. (jonathan@tangential.ca)
196196
. Added the TCP_SYNCNT constant for Linux to set number of attempts to send
197197
SYN packets from the client. (David Carlier)
198-
. Added the SO_EXCLBIND constant for exclusive socket binding on illumos/solaris.
198+
. Added the SO_EXCLBIND constant for exclusive socket binding on illumos/solaris.
199199
(David Carlier)
200200

201201
- SNMP:

‎ext/mbstring/mbstring.c‎

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6119,6 +6119,9 @@ static zend_string* mb_mime_header_encode(zend_string *input, const mbfl_encodin
61196119
unsigned char *in = (unsigned char*)ZSTR_VAL(input);
61206120
size_t in_len = ZSTR_LEN(input);
61216121

6122+
ZEND_ASSERT(outcode->mime_name != NULL);
6123+
ZEND_ASSERT(outcode->mime_name[0] != '0円');
6124+
61226125
if (!in_len) {
61236126
return zend_empty_string;
61246127
}
@@ -6141,7 +6144,8 @@ static zend_string* mb_mime_header_encode(zend_string *input, const mbfl_encodin
61416144
unsigned int state = 0;
61426145
/* wchar_buf should be big enough that when it is full, we definitely have enough
61436146
* wchars to fill an entire line of output */
6144-
uint32_t wchar_buf[80];
6147+
const size_t wchar_buf_len = 90;
6148+
uint32_t wchar_buf[wchar_buf_len];
61456149
uint32_t *p, *e;
61466150
/* What part of wchar_buf is filled with still-unprocessed data which should not
61476151
* be overwritten? */
@@ -6152,7 +6156,7 @@ static zend_string* mb_mime_header_encode(zend_string *input, const mbfl_encodin
61526156
* spaces), just pass it through unchanged */
61536157
bool checking_leading_spaces = true;
61546158
while (in_len) {
6155-
size_t out_len = incode->to_wchar(&in, &in_len, wchar_buf, 80, &state);
6159+
size_t out_len = incode->to_wchar(&in, &in_len, wchar_buf, wchar_buf_len, &state);
61566160
p = wchar_buf;
61576161
e = wchar_buf + out_len;
61586162

@@ -6186,9 +6190,9 @@ no_passthrough: ;
61866190
* do so all the way to the end of the string */
61876191
while (in_len) {
61886192
/* Decode part of the input string, refill wchar_buf */
6189-
ZEND_ASSERT(offset <80);
6190-
size_t out_len = incode->to_wchar(&in, &in_len, wchar_buf + offset, 80 - offset, &state);
6191-
ZEND_ASSERT(out_len <= 80 - offset);
6193+
ZEND_ASSERT(offset +MBSTRING_MIN_WCHAR_BUFSIZE <= wchar_buf_len);
6194+
size_t out_len = incode->to_wchar(&in, &in_len, wchar_buf + offset, wchar_buf_len - offset, &state);
6195+
ZEND_ASSERT(out_len <= wchar_buf_len - offset);
61926196
p = wchar_buf;
61936197
e = wchar_buf + offset + out_len;
61946198
/* ASCII output is broken into space-delimited 'words'
@@ -6209,6 +6213,7 @@ no_passthrough: ;
62096213
* If we are already too far along on a line to include Base64/QPrint encoded data
62106214
* on the same line (without overrunning max line length), then add a line feed
62116215
* right now */
6216+
feed_and_mime_encode:
62126217
if (mb_convert_buf_len(&buf) - line_start + indent + strlen(outcode->mime_name) > 55) {
62136218
MB_CONVERT_BUF_ENSURE(&buf, buf.out, buf.limit, (e - word_start) + linefeed_len + 1);
62146219
buf.out = mb_convert_buf_appendn(buf.out, linefeed, linefeed_len);
@@ -6246,7 +6251,13 @@ no_passthrough: ;
62466251

62476252
if (in_len) {
62486253
/* Copy chars which are part of an incomplete 'word' to the beginning
6249-
* of wchar_buf and reprocess them on the next iteration */
6254+
* of wchar_buf and reprocess them on the next iteration.
6255+
* But first make sure that the incomplete 'word' isn't so big that
6256+
* there will be no space to add any more decoded wchars in the buffer
6257+
* (which could lead to an infinite loop) */
6258+
if ((word_start - wchar_buf) < MBSTRING_MIN_WCHAR_BUFSIZE) {
6259+
goto feed_and_mime_encode;
6260+
}
62506261
offset = e - word_start;
62516262
if (offset) {
62526263
memmove(wchar_buf, word_start, offset * sizeof(uint32_t));
@@ -6288,17 +6299,17 @@ mime_encoding_needed: ;
62886299

62896300
/* Do we need to refill wchar_buf to make sure we don't run out of wchars
62906301
* in the middle of a line? */
6291-
if (p == wchar_buf) {
6302+
offset = e - p;
6303+
if (wchar_buf_len - offset < MBSTRING_MIN_WCHAR_BUFSIZE) {
62926304
goto start_new_line;
62936305
}
6294-
offset = e - p;
62956306
memmove(wchar_buf, p, offset * sizeof(uint32_t));
62966307

62976308
while(true) {
62986309
refill_wchar_buf: ;
6299-
ZEND_ASSERT(offset <80);
6300-
size_t out_len = incode->to_wchar(&in, &in_len, wchar_buf + offset, 80 - offset, &state);
6301-
ZEND_ASSERT(out_len <= 80 - offset);
6310+
ZEND_ASSERT(offset +MBSTRING_MIN_WCHAR_BUFSIZE <= wchar_buf_len);
6311+
size_t out_len = incode->to_wchar(&in, &in_len, wchar_buf + offset, wchar_buf_len - offset, &state);
6312+
ZEND_ASSERT(out_len <= wchar_buf_len - offset);
63026313
p = wchar_buf;
63036314
e = wchar_buf + offset + out_len;
63046315

@@ -6373,22 +6384,18 @@ start_new_line: ;
63736384

63746385
indent = 0; /* Indent argument must only affect the first line */
63756386

6376-
if (in_len) {
6377-
/* We still have more of input string remaining to decode */
6387+
if (in_len||p<e) {
6388+
/* We still have more input to process */
63786389
buf.out = mb_convert_buf_appendn(buf.out, linefeed, linefeed_len);
63796390
buf.out = mb_convert_buf_add(buf.out, ' ');
63806391
line_start = mb_convert_buf_len(&buf);
6381-
/* Copy remaining wchars to beginning of buffer so they will be
6382-
* processed on the next iteration of outer 'do' loop */
63836392
offset = e - p;
6384-
memmove(wchar_buf, p, offset * sizeof(uint32_t));
6385-
goto refill_wchar_buf;
6386-
} else if (p < e) {
6387-
/* Input string is finished, but we still have trailing wchars
6388-
* remaining to be processed in wchar_buf */
6389-
buf.out = mb_convert_buf_appendn(buf.out, linefeed, linefeed_len);
6390-
buf.out = mb_convert_buf_add(buf.out, ' ');
6391-
line_start = mb_convert_buf_len(&buf);
6393+
if (in_len && (wchar_buf_len - offset >= MBSTRING_MIN_WCHAR_BUFSIZE)) {
6394+
/* Copy any remaining wchars to beginning of buffer and refill
6395+
* the rest of the buffer */
6396+
memmove(wchar_buf, p, offset * sizeof(uint32_t));
6397+
goto refill_wchar_buf;
6398+
}
63926399
goto start_new_line;
63936400
} else {
63946401
/* We are done! */
@@ -6426,7 +6433,7 @@ PHP_FUNCTION(mb_encode_mimeheader)
64266433
charset = php_mb_get_encoding(charset_name, 2);
64276434
if (!charset) {
64286435
RETURN_THROWS();
6429-
} else if (charset->mime_name == NULL || charset->mime_name[0] == '0円') {
6436+
} else if (charset->mime_name == NULL || charset->mime_name[0] == '0円'||charset==&mbfl_encoding_qprint) {
64306437
zend_argument_value_error(2, "\"%s\" cannot be used for MIME header encoding", ZSTR_VAL(charset_name));
64316438
RETURN_THROWS();
64326439
}

‎ext/mbstring/tests/mb_encode_mimeheader_basic4.phpt‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Test mb_encode_mimeheader() function : test cases found by fuzzer
33
--EXTENSIONS--
44
mbstring
5+
--INI--
6+
error_reporting=E_ALL^E_DEPRECATED
57
--FILE--
68
<?php
79

@@ -115,7 +117,25 @@ var_dump(mb_encode_mimeheader("\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
115117
// In the general case, matching the old implementation's decision to transfer-encode or not
116118
// perfectly would require allocating potentially unbounded scratch memory (up to the size of
117119
// the input string), but we aim to only use a constant amount of temporarily allocated memory
118-
var_dump(mb_encode_mimeheader("2\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20!3", "GB18030", "Q", ""));
120+
var_dump(mb_encode_mimeheader("2\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20!3", "GB18030", "Q", ""));
121+
122+
// Regression test for infinite loop which was unintentionally caused when refactoring
123+
var_dump(mb_encode_mimeheader(",9868949,9868978,9869015,9689100,9869121,9869615,9870690,9867116,98558119861183. ", "utf-8", "B"));
124+
var_dump(mb_encode_mimeheader('xx ' . str_repeat("A", 81) . "", "utf-8", "B"));
125+
126+
// Regression test for problem where MIME encoding loop would not leave enough space in wchar
127+
// buffer for the next iteration, causing an assertion failure
128+
mb_internal_encoding('MacJapanese');
129+
var_dump(mb_encode_mimeheader("ne\xf6\xff\xff\xffs\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff1\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff1", 'CP50220', 'B', "A", 44));
130+
131+
// Regression test for failing assertion caused by the fact that QPrint deliberately generates no
132+
// wchars for CR (0x0D) bytes
133+
try {
134+
mb_internal_encoding('Quoted-Printable');
135+
var_dump(mb_encode_mimeheader("=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=00=00=00=00=00=00=00=01=00=00=00=00=00=00=00850r=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=0D=00=00=00=0050r=08=0DCP850r850r0r", "Quoted-Printable", "B", "", 184));
136+
} catch (\ValueError $e) {
137+
echo $e->getMessage() . \PHP_EOL;
138+
}
119139

120140
echo "Done";
121141
?>
@@ -156,5 +176,11 @@ string(75) " 111111111111111111111111111111111111111111111111111111111111111111
156176
string(33) "=?HZ-GB-2312?Q?=7E=7Bs=5B=7E=7D?="
157177
string(77) "2 !3"
158178
string(282) "=?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20!=33=20?="
159-
string(296) "2 =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20!=33?="
179+
string(344) "2 =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?GB18030?Q?=20=20=20=20=20=20=20=20=20!=33?="
180+
string(135) "=?UTF-8?B?LDk4Njg5NDksOTg2ODk3OCw5ODY5MDE1LDk2ODkxMDAsOTg2OTEyMSw5ODY5?=
181+
=?UTF-8?B?NjE1LDk4NzA2OTAsOTg2NzExNiw5ODU1ODExOTg2MTE4My4g?="
182+
string(142) "xx =?UTF-8?B?QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB?=
183+
=?UTF-8?B?QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBIA==?="
184+
string(690) "=?ISO-2022-JP?B?bmU/?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/cxskQiFEGyhCPw==?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/MRskQiFEGyhCPxskQiFEGyhCPw==?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/GyRCIUQbKEI/?=A =?ISO-2022-JP?B?GyRCIUQbKEI/GyRCIUQbKEI/MQ==?="
185+
mb_encode_mimeheader(): Argument #2 ($charset) "Quoted-Printable" cannot be used for MIME header encoding
160186
Done

‎ext/standard/password.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ static zend_string* php_password_bcrypt_hash(const zend_string *password, zend_a
181181
zval *zcost;
182182
zend_long cost = PHP_PASSWORD_BCRYPT_COST;
183183

184+
if (memchr(ZSTR_VAL(password), '0円', ZSTR_LEN(password))) {
185+
zend_value_error("Bcrypt password must not contain null character");
186+
return NULL;
187+
}
188+
184189
if (options && (zcost = zend_hash_str_find(options, "cost", sizeof("cost")-1)) != NULL) {
185190
cost = zval_get_long(zcost);
186191
}

‎ext/standard/proc_open.c‎

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -536,11 +536,32 @@ static void append_backslashes(smart_str *str, size_t num_bs)
536536
}
537537
}
538538

539-
/* See https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments */
540-
static void append_win_escaped_arg(smart_str *str, zend_string *arg)
539+
const char *special_chars = "()!^\"<>&|%";
540+
541+
static bool is_special_character_present(const zend_string *arg)
542+
{
543+
for (size_t i = 0; i < ZSTR_LEN(arg); ++i) {
544+
if (strchr(special_chars, ZSTR_VAL(arg)[i]) != NULL) {
545+
return true;
546+
}
547+
}
548+
return false;
549+
}
550+
551+
/* See https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments and
552+
* https://learn.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way */
553+
static void append_win_escaped_arg(smart_str *str, zend_string *arg, bool is_cmd_argument)
541554
{
542555
size_t num_bs = 0;
556+
bool has_special_character = false;
543557

558+
if (is_cmd_argument) {
559+
has_special_character = is_special_character_present(arg);
560+
if (has_special_character) {
561+
/* Escape double quote with ^ if executed by cmd.exe. */
562+
smart_str_appendc(str, '^');
563+
}
564+
}
544565
smart_str_appendc(str, '"');
545566
for (size_t i = 0; i < ZSTR_LEN(arg); ++i) {
546567
char c = ZSTR_VAL(arg)[i];
@@ -554,18 +575,71 @@ static void append_win_escaped_arg(smart_str *str, zend_string *arg)
554575
num_bs = num_bs * 2 + 1;
555576
}
556577
append_backslashes(str, num_bs);
578+
if (has_special_character && strchr(special_chars, c) != NULL) {
579+
/* Escape special chars with ^ if executed by cmd.exe. */
580+
smart_str_appendc(str, '^');
581+
}
557582
smart_str_appendc(str, c);
558583
num_bs = 0;
559584
}
560585
append_backslashes(str, num_bs * 2);
586+
if (has_special_character) {
587+
/* Escape double quote with ^ if executed by cmd.exe. */
588+
smart_str_appendc(str, '^');
589+
}
561590
smart_str_appendc(str, '"');
562591
}
563592

593+
static inline int stricmp_end(const char* suffix, const char* str) {
594+
size_t suffix_len = strlen(suffix);
595+
size_t str_len = strlen(str);
596+
597+
if (suffix_len > str_len) {
598+
return -1; /* Suffix is longer than string, cannot match. */
599+
}
600+
601+
/* Compare the end of the string with the suffix, ignoring case. */
602+
return _stricmp(str + (str_len - suffix_len), suffix);
603+
}
604+
605+
static bool is_executed_by_cmd(const char *prog_name)
606+
{
607+
/* If program name is cmd.exe, then return true. */
608+
if (_stricmp("cmd.exe", prog_name) == 0 || _stricmp("cmd", prog_name) == 0
609+
|| stricmp_end("\\cmd.exe", prog_name) == 0 || stricmp_end("\\cmd", prog_name) == 0) {
610+
return true;
611+
}
612+
613+
/* Find the last occurrence of the directory separator (backslash or forward slash). */
614+
char *last_separator = strrchr(prog_name, '\\');
615+
char *last_separator_fwd = strrchr(prog_name, '/');
616+
if (last_separator_fwd && (!last_separator || last_separator < last_separator_fwd)) {
617+
last_separator = last_separator_fwd;
618+
}
619+
620+
/* Find the last dot in the filename after the last directory separator. */
621+
char *extension = NULL;
622+
if (last_separator != NULL) {
623+
extension = strrchr(last_separator, '.');
624+
} else {
625+
extension = strrchr(prog_name, '.');
626+
}
627+
628+
if (extension == NULL || extension == prog_name) {
629+
/* No file extension found, it is not batch file. */
630+
return false;
631+
}
632+
633+
/* Check if the file extension is ".bat" or ".cmd" which is always executed by cmd.exe. */
634+
return _stricmp(extension, ".bat") == 0 || _stricmp(extension, ".cmd") == 0;
635+
}
636+
564637
static zend_string *create_win_command_from_args(HashTable *args)
565638
{
566639
smart_str str = {0};
567640
zval *arg_zv;
568-
bool is_prog_name = 1;
641+
bool is_prog_name = true;
642+
bool is_cmd_execution = false;
569643
int elem_num = 0;
570644

571645
ZEND_HASH_FOREACH_VAL(args, arg_zv) {
@@ -575,11 +649,13 @@ static zend_string *create_win_command_from_args(HashTable *args)
575649
return NULL;
576650
}
577651

578-
if (!is_prog_name) {
652+
if (is_prog_name) {
653+
is_cmd_execution = is_executed_by_cmd(ZSTR_VAL(arg_str));
654+
} else {
579655
smart_str_appendc(&str, ' ');
580656
}
581657

582-
append_win_escaped_arg(&str, arg_str);
658+
append_win_escaped_arg(&str, arg_str, !is_prog_name&&is_cmd_execution);
583659

584660
is_prog_name = 0;
585661
zend_string_release(arg_str);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
GHSA-54hq-v5wp-fqgv - proc_open does not correctly escape args for bat files
3+
--SKIPIF--
4+
<?php
5+
if( substr(PHP_OS, 0, 3) != "WIN" )
6+
die('skip Run only on Windows');
7+
?>
8+
--FILE--
9+
<?php
10+
11+
$batch_file_content = <<<EOT
12+
@echo off
13+
powershell -Command "Write-Output '%1%'"
14+
EOT;
15+
$batch_file_path = __DIR__ . '/ghsa-54hq-v5wp-fqgv.bat';
16+
17+
file_put_contents($batch_file_path, $batch_file_content);
18+
19+
$descriptorspec = [STDIN, STDOUT, STDOUT];
20+
$proc = proc_open([$batch_file_path, "\"&notepad.exe"], $descriptorspec, $pipes);
21+
proc_close($proc);
22+
23+
?>
24+
--EXPECT--
25+
"&notepad.exe
26+
--CLEAN--
27+
<?php
28+
@unlink(__DIR__ . '/ghsa-54hq-v5wp-fqgv.bat');
29+
?>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
GHSA-54hq-v5wp-fqgv - proc_open does not correctly escape args for cmd files
3+
--SKIPIF--
4+
<?php
5+
if( substr(PHP_OS, 0, 3) != "WIN" )
6+
die('skip Run only on Windows');
7+
?>
8+
--FILE--
9+
<?php
10+
11+
$batch_file_content = <<<EOT
12+
@echo off
13+
powershell -Command "Write-Output '%1%'"
14+
EOT;
15+
$batch_file_path = __DIR__ . '/ghsa-54hq-v5wp-fqgv.cmd';
16+
17+
file_put_contents($batch_file_path, $batch_file_content);
18+
19+
$descriptorspec = [STDIN, STDOUT, STDOUT];
20+
$proc = proc_open([$batch_file_path, "\"&notepad<>^()!.exe"], $descriptorspec, $pipes);
21+
proc_close($proc);
22+
23+
?>
24+
--EXPECT--
25+
"&notepad<>^()!.exe
26+
--CLEAN--
27+
<?php
28+
@unlink(__DIR__ . '/ghsa-54hq-v5wp-fqgv.cmd');
29+
?>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /