Skip to content

Commit d4b78af

Browse files
authored
Merge pull request #12 from php/master
sync
2 parents 7fa87be + 051b396 commit d4b78af

File tree

362 files changed

+8943
-5527
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

362 files changed

+8943
-5527
lines changed

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Bug report
2+
description: Create a bug report
3+
labels: ["Bug", "Status: Needs Triage"]
4+
body:
5+
- type: textarea
6+
attributes:
7+
label: Description
8+
description: "Please provide a minimal way to reproduce the problem and describe what the expected vs actual behavior is. Provide a [3v4l.org](https://3v4l.org/) link if possible."
9+
value: |
10+
The following code:
11+
12+
```php
13+
<?php
14+
```
15+
16+
Resulted in this output:
17+
```
18+
```
19+
20+
But I expected this output instead:
21+
```
22+
```
23+
validations:
24+
required: true
25+
- type: input
26+
attributes:
27+
label: PHP Version
28+
description: "The used PHP version. Make sure it is [supported](https://www.php.net/supported-versions.php)."
29+
placeholder: "PHP 8.0.12"
30+
validations:
31+
required: true
32+
- type: input
33+
attributes:
34+
label: Operating System
35+
description: "The used operating system, if relevant."
36+
placeholder: "Ubuntu 20.04"

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: Documentation issue
4+
url: https://github.com/php/doc-en/issues
5+
about: Please report documentation issues on the doc-en repository.
6+
- name: Security issue
7+
url: https://bugs.php.net/report.php?security_bug
8+
about: Please report security issues in this private bug tracker.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: Feature request
2+
description: Create a feature request
3+
labels: ["Feature", "Status: Needs Triage"]
4+
body:
5+
- type: textarea
6+
attributes:
7+
label: Description
8+
description: "Please describe the requested feature and why it should be included in PHP."
9+
validations:
10+
required: true
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Close old issues that need feedback
2+
3+
on:
4+
schedule:
5+
- cron: "0 0 * * *"
6+
7+
jobs:
8+
build:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Close old issues that need feedback
12+
uses: dwieeb/needs-reply@v2
13+
with:
14+
repo-token: ${{ secrets.GITHUB_TOKEN }}
15+
issue-label: "Status: Needs Feedback"
16+
days-before-close: 14
17+
close-message: "No feedback was provided. The issue is being suspended because we assume that you are no longer experiencing the problem. If this is not the case and you are able to provide the information that was requested earlier, please do so. Thank you."
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: Remove needs feedback label
2+
3+
on:
4+
issue_comment:
5+
types:
6+
- created
7+
8+
jobs:
9+
build:
10+
if: "contains(github.event.issue.labels.*.name, 'Status: Needs Feedback') && github.event.issue.user.login == github.event.sender.login"
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions-ecosystem/action-remove-labels@v1
14+
with:
15+
labels: "Status: Needs Feedback"

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ PHP NEWS
1414
- OCI8:
1515
. Added oci8.prefetch_lob_size directive to tune LOB query performance
1616

17+
- Standard:
18+
. net_get_interfaces() also reports wireless network interfaces on Windows.
19+
(Yurun)
20+
1721
- Zip:
1822
. add ZipArchive::clearError() method
1923
. add ZipArchive::getStreamName() method

TSRM/TSRM.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,10 @@ TSRM_API const char *tsrm_api_name(void);
167167
#define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)])
168168
#define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element)
169169
#define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset)))
170-
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR;
171-
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;
170+
#define TSRMLS_MAIN_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR;
171+
#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;
172+
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
173+
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
172174
#define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
173175
#define TSRMLS_CACHE _tsrm_ls_cache
174176

@@ -182,6 +184,8 @@ TSRM_API const char *tsrm_api_name(void);
182184
#define tsrm_env_unlock()
183185

184186
#define TSRMG_STATIC(id, type, element)
187+
#define TSRMLS_MAIN_CACHE_EXTERN()
188+
#define TSRMLS_MAIN_CACHE_DEFINE()
185189
#define TSRMLS_CACHE_EXTERN()
186190
#define TSRMLS_CACHE_DEFINE()
187191
#define TSRMLS_CACHE_UPDATE()

UPGRADING

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ PHP 8.2 UPGRADE NOTES
4848
========================================
4949

5050
- Core:
51+
. Creation of dynamic properties is deprecated, unless the class opts in by
52+
using the #[AllowDynamicProperties] attribute. stdClass allows dynamic
53+
properties. Usage of __get()/__set() is not affected by this change. A
54+
dynamic properties deprecation warning can be addressed by:
55+
- Declaring the property (preferred).
56+
- Adding the #[AllowDynamicProperties] attribute to the class (which also
57+
applies to all child classes).
58+
- Using a WeakMap if you wish to associate additional data with an object
59+
you do not own.
60+
5161
. Callables that are not accepted by the $callable() syntax (but are accepted
5262
by call_user_func) are deprecated. In particular:
5363

Zend/Optimizer/dce.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ static inline bool may_have_side_effects(
111111
case ZEND_ROPE_INIT:
112112
case ZEND_ROPE_ADD:
113113
case ZEND_INIT_ARRAY:
114-
case ZEND_ADD_ARRAY_ELEMENT:
115114
case ZEND_SPACESHIP:
116115
case ZEND_STRLEN:
117116
case ZEND_COUNT:
@@ -128,6 +127,12 @@ static inline bool may_have_side_effects(
128127
case ZEND_ARRAY_KEY_EXISTS:
129128
/* No side effects */
130129
return 0;
130+
case ZEND_ADD_ARRAY_ELEMENT:
131+
/* TODO: We can't free two vars. Keep instruction alive. <?php [0, "$a" => "$b"]; */
132+
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && (opline->op2_type & (IS_VAR|IS_TMP_VAR))) {
133+
return 1;
134+
}
135+
return 0;
131136
case ZEND_ROPE_END:
132137
/* TODO: Rope dce optimization, see #76446 */
133138
return 1;
@@ -514,6 +519,10 @@ static inline bool may_break_varargs(const zend_op_array *op_array, const zend_s
514519
return 0;
515520
}
516521

522+
static inline bool may_throw_dce_exception(const zend_op *opline) {
523+
return opline->opcode == ZEND_ADD_ARRAY_ELEMENT && opline->op2_type == IS_UNUSED;
524+
}
525+
517526
int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, bool reorder_dtor_effects) {
518527
int i;
519528
zend_ssa_phi *phi;
@@ -580,7 +589,8 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, bool reorder_d
580589
add_operands_to_worklists(&ctx, &op_array->opcodes[op_data], &ssa->ops[op_data], ssa, 0);
581590
}
582591
} else if (may_have_side_effects(op_array, ssa, &op_array->opcodes[i], &ssa->ops[i], ctx.reorder_dtor_effects)
583-
|| zend_may_throw(&op_array->opcodes[i], &ssa->ops[i], op_array, ssa)
592+
|| (zend_may_throw(&op_array->opcodes[i], &ssa->ops[i], op_array, ssa)
593+
&& !may_throw_dce_exception(&op_array->opcodes[i]))
584594
|| (has_varargs && may_break_varargs(op_array, ssa, &ssa->ops[i]))) {
585595
if (op_array->opcodes[i].opcode == ZEND_NEW
586596
&& op_array->opcodes[i+1].opcode == ZEND_DO_FCALL

Zend/Optimizer/dfa_pass.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -345,19 +345,17 @@ static bool opline_supports_assign_contraction(
345345
return 1;
346346
}
347347

348-
static bool variable_redefined_in_range(zend_ssa *ssa, int var, int start, int end)
348+
static bool variable_defined_or_used_in_range(zend_ssa *ssa, int var, int start, int end)
349349
{
350350
while (start < end) {
351-
if (ssa->ops[start].op1_def >= 0
352-
&& ssa->vars[ssa->ops[start].op1_def].var == var) {
353-
return 1;
354-
}
355-
if (ssa->ops[start].op2_def >= 0
356-
&& ssa->vars[ssa->ops[start].op2_def].var == var) {
357-
return 1;
358-
}
359-
if (ssa->ops[start].result_def >= 0
360-
&& ssa->vars[ssa->ops[start].result_def].var == var) {
351+
const zend_ssa_op *ssa_op = &ssa->ops[start];
352+
if ((ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].var == var) ||
353+
(ssa_op->op2_def >= 0 && ssa->vars[ssa_op->op2_def].var == var) ||
354+
(ssa_op->result_def >= 0 && ssa->vars[ssa_op->result_def].var == var) ||
355+
(ssa_op->op1_use >= 0 && ssa->vars[ssa_op->op1_use].var == var) ||
356+
(ssa_op->op2_use >= 0 && ssa->vars[ssa_op->op2_use].var == var) ||
357+
(ssa_op->result_use >= 0 && ssa->vars[ssa_op->result_use].var == var)
358+
) {
361359
return 1;
362360
}
363361
start++;
@@ -1331,7 +1329,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
13311329
&& opline_supports_assign_contraction(
13321330
ssa, &op_array->opcodes[ssa->vars[src_var].definition],
13331331
src_var, opline->result.var)
1334-
&& !variable_redefined_in_range(ssa, EX_VAR_TO_NUM(opline->result.var),
1332+
&& !variable_defined_or_used_in_range(ssa, EX_VAR_TO_NUM(opline->result.var),
13351333
ssa->vars[src_var].definition+1, op_1)
13361334
) {
13371335

@@ -1490,7 +1488,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
14901488
&& opline_supports_assign_contraction(
14911489
ssa, &op_array->opcodes[ssa->vars[src_var].definition],
14921490
src_var, opline->op1.var)
1493-
&& !variable_redefined_in_range(ssa, EX_VAR_TO_NUM(opline->op1.var),
1491+
&& !variable_defined_or_used_in_range(ssa, EX_VAR_TO_NUM(opline->op1.var),
14941492
ssa->vars[src_var].definition+1, op_1)
14951493
) {
14961494

Zend/Optimizer/sccp.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,9 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
11011101

11021102
/* Don't try to propagate assignments to (potentially) typed properties. We would
11031103
* need to deal with errors and type conversions first. */
1104-
if (!var_info->ce || (var_info->ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
1104+
// TODO: Distinguish dynamic and declared property assignments here?
1105+
if (!var_info->ce || (var_info->ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) ||
1106+
!(var_info->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
11051107
SET_RESULT_BOT(result);
11061108
SET_RESULT_BOT(op1);
11071109
return;
@@ -2277,6 +2279,12 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
22772279
return 0;
22782280
}
22792281
break;
2282+
case ZEND_INIT_ARRAY:
2283+
case ZEND_ADD_ARRAY_ELEMENT:
2284+
if (opline->op2_type == IS_UNUSED) {
2285+
return 0;
2286+
}
2287+
/* break missing intentionally */
22802288
default:
22812289
if (zend_may_throw(opline, ssa_op, op_array, ssa)) {
22822290
return 0;

Zend/Optimizer/scdf.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,29 +224,32 @@ static uint32_t cleanup_loop_var_free_block(scdf_ctx *scdf, zend_basic_block *bl
224224
zend_ssa *ssa = scdf->ssa;
225225
const zend_op_array *op_array = scdf->op_array;
226226
const zend_cfg *cfg = &ssa->cfg;
227+
int block_num = block - cfg->blocks;
227228
uint32_t removed_ops = 0;
228229

229230
/* Removes phi nodes */
230-
for (zend_ssa_phi *phi = ssa->blocks[block - cfg->blocks].phis; phi; phi = phi->next) {
231+
for (zend_ssa_phi *phi = ssa->blocks[block_num].phis; phi; phi = phi->next) {
231232
zend_ssa_remove_uses_of_var(ssa, phi->ssa_var);
232233
zend_ssa_remove_phi(ssa, phi);
233234
}
234235

235236
for (uint32_t i = block->start; i < block->start + block->len; i++) {
236237
zend_op *opline = &op_array->opcodes[i];
237238
zend_ssa_op *ssa_op = &scdf->ssa->ops[i];
238-
if (is_live_loop_var_free(scdf, opline, ssa_op)) {
239+
if (opline->opcode == ZEND_NOP
240+
|| is_live_loop_var_free(scdf, opline, ssa_op)) {
239241
continue;
240242
}
241243

242244
/* While we have to preserve the loop var free, we can still remove other instructions
243245
* in the block. */
244246
zend_ssa_remove_defs_of_instr(ssa, ssa_op);
245247
zend_ssa_remove_instr(ssa, opline, ssa_op);
248+
removed_ops++;
246249
}
247250

248-
/* This block has no predecessors anymore. */
249-
block->predecessors_count = 0;
251+
zend_ssa_remove_block_from_cfg(ssa, block_num);
252+
250253
return removed_ops;
251254
}
252255

Zend/Optimizer/ssa_integrity.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ static inline bool is_var_type(zend_uchar type) {
8989
return (type & (IS_CV|IS_VAR|IS_TMP_VAR)) != 0;
9090
}
9191

92+
static inline bool is_defined(const zend_ssa *ssa, const zend_op_array *op_array, int var) {
93+
const zend_ssa_var *ssa_var = &ssa->vars[var];
94+
return ssa_var->definition >= 0 || ssa_var->definition_phi || var < op_array->last_var;
95+
}
96+
9297
#define FAIL(...) do { \
9398
if (status == SUCCESS) { \
9499
fprintf(stderr, "\nIn function %s::%s (%s):\n", \
@@ -209,6 +214,10 @@ void ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ex
209214
if (ssa_op->op1_use >= ssa->vars_count) {
210215
FAIL("op1 use %d out of range\n", ssa_op->op1_use);
211216
}
217+
if (!is_defined(ssa, op_array, ssa_op->op1_use)) {
218+
FAIL("op1 use of " VARFMT " in " INSTRFMT " is not defined\n",
219+
VAR(ssa_op->op1_use), INSTR(i));
220+
}
212221
if (!is_in_use_chain(ssa, ssa_op->op1_use, i)) {
213222
FAIL("op1 use of " VARFMT " in " INSTRFMT " not in use chain\n",
214223
VAR(ssa_op->op1_use), INSTR(i));
@@ -222,6 +231,10 @@ void ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ex
222231
if (ssa_op->op2_use >= ssa->vars_count) {
223232
FAIL("op2 use %d out of range\n", ssa_op->op2_use);
224233
}
234+
if (!is_defined(ssa, op_array, ssa_op->op2_use)) {
235+
FAIL("op2 use of " VARFMT " in " INSTRFMT " is not defined\n",
236+
VAR(ssa_op->op2_use), INSTR(i));
237+
}
225238
if (!is_in_use_chain(ssa, ssa_op->op2_use, i)) {
226239
FAIL("op2 use of " VARFMT " in " INSTRFMT " not in use chain\n",
227240
VAR(ssa_op->op2_use), INSTR(i));
@@ -235,6 +248,10 @@ void ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ex
235248
if (ssa_op->result_use >= ssa->vars_count) {
236249
FAIL("result use %d out of range\n", ssa_op->result_use);
237250
}
251+
if (!is_defined(ssa, op_array, ssa_op->result_use)) {
252+
FAIL("result use of " VARFMT " in " INSTRFMT " is not defined\n",
253+
VAR(ssa_op->result_use), INSTR(i));
254+
}
238255
if (!is_in_use_chain(ssa, ssa_op->result_use, i)) {
239256
FAIL("result use of " VARFMT " in " INSTRFMT " not in use chain\n",
240257
VAR(ssa_op->result_use), INSTR(i));

0 commit comments

Comments
 (0)