Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b0d95ab
Add namespace_name field to zend_op_array for visibility checks
withinboredom Nov 7, 2025
9de32b4
Define visibility flags for namespace-scoped members
withinboredom Nov 7, 2025
210d6e1
Implement namespace extraction utilities for visibility checks
withinboredom Nov 7, 2025
51415d9
Parse private(namespace) visibility modifier
withinboredom Nov 7, 2025
0f92c6a
Validate private(namespace) visibility modifier combinations
withinboredom Nov 7, 2025
21fd83c
Update tokenizer data for private(namespace) tokens
withinboredom Nov 7, 2025
22194b3
Prevent reducing visibility to private(namespace) in child classes
withinboredom Nov 7, 2025
4f70a41
Enforce namespace-scoped visibility for method calls
withinboredom Nov 7, 2025
50eec2e
Enforce namespace-scoped visibility for property access
withinboredom Nov 7, 2025
b8d8a49
Add Reflection support for namespace visibility
withinboredom Nov 7, 2025
e9e815b
Fix critical bug and implement property/method namespace visibility
withinboredom Nov 7, 2025
69ca92c
Add comprehensive test suite for private(namespace) visibility
withinboredom Nov 7, 2025
6ca49d4
fix memory leak in arena-alloc'd classes
withinboredom Nov 8, 2025
2247bec
Fix memory leak, callable validation, and edge cases for private(name…
withinboredom Nov 8, 2025
f478640
Fix heap-use-after-free in closure namespace_name handling
withinboredom Nov 8, 2025
63053a2
Fix namespace_name memory leaks in function copying/binding
withinboredom Nov 8, 2025
48bf396
Fix private(namespace) callable validation error messages
withinboredom Nov 8, 2025
7c17076
Fix private(namespace) visibility checks for callables and update tests
withinboredom Nov 8, 2025
5bc45dc
Add comprehensive property hooks tests for private(namespace)
withinboredom Nov 8, 2025
3ae5252
Fix memory leak in lexer token string allocation
withinboredom Nov 8, 2025
76003c4
Fix private(namespace) visibility in eval with explicit namespace
withinboredom Nov 8, 2025
b11fb62
Fix opcache memory leak for namespace_name in op_arrays
withinboredom Nov 8, 2025
f8e98aa
Fix memory leak in lexer by cleaning up tokens at restart label
withinboredom Nov 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_array_map_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
private(namespace) method with array_map - same namespace
--FILE--
<?php

namespace Foo;

class A {
private(namespace) static function double($x) {
return $x * 2;
}
}

// Same namespace - should work
$result = array_map([A::class, 'double'], [1, 2, 3]);
var_dump($result);

?>
--EXPECT--
array(3) {
[0]=>
int(2)
[1]=>
int(4)
[2]=>
int(6)
}
26 changes: 26 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_array_map_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
private(namespace) method with array_map - different namespace
--FILE--
<?php

namespace Foo {
class A {
private(namespace) static function double($x) {
return $x * 2;
}
}
}

namespace Bar {
// Different namespace - should fail
$result = array_map(['\Foo\A', 'double'], [1, 2, 3]);
var_dump($result);
}

?>
--EXPECTF--
Fatal error: Uncaught TypeError: array_map(): Argument #1 ($callback) must be a valid callback or null, cannot access private(namespace) method Foo\A::double() in %s:%d
Stack trace:
#0 %s(%d): array_map(Array, Array)
#1 {main}
thrown in %s on line %d
24 changes: 24 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_asymmetric_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
Asymmetric visibility: public private(namespace)(set) property - read from same namespace
--FILE--
<?php

namespace App {
class Config {
public private(namespace)(set) int $value = 100;
}

class ConfigManager {
public function getValue(): int {
$config = new Config();
return $config->value;
}
}

$manager = new ConfigManager();
echo $manager->getValue() . "\n";
}

?>
--EXPECT--
100
25 changes: 25 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_asymmetric_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
Asymmetric visibility: public private(namespace)(set) property - write from same namespace
--FILE--
<?php

namespace App {
class Config {
public private(namespace)(set) int $value = 100;
}

class ConfigManager {
public function setValue(): void {
$config = new Config();
$config->value = 200;
echo $config->value . "\n";
}
}

$manager = new ConfigManager();
$manager->setValue();
}

?>
--EXPECT--
200
30 changes: 30 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_asymmetric_003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--TEST--
Asymmetric visibility: public private(namespace)(set) property - write from different namespace fails
--FILE--
<?php

namespace App {
class Config {
public private(namespace)(set) int $value = 100;
}
}

namespace Other {
class Consumer {
public function tryWrite(): void {
$config = new \App\Config();
$config->value = 200;
}
}

$consumer = new Consumer();
$consumer->tryWrite();
}

?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify private(namespace)(set) property App\Config::$value from scope Other\Consumer in %s:%d
Stack trace:
#0 %s(%d): Other\Consumer->tryWrite()
#1 {main}
thrown in %s on line %d
26 changes: 26 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_asymmetric_004.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
Asymmetric visibility: public private(namespace)(set) property - read from different namespace succeeds
--FILE--
<?php

namespace App {
class Config {
public private(namespace)(set) int $value = 100;
}
}

namespace Other {
class Consumer {
public function readValue(): int {
$config = new \App\Config();
return $config->value;
}
}

$consumer = new Consumer();
echo $consumer->readValue() . "\n";
}

?>
--EXPECT--
100
23 changes: 23 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_basic_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
private(namespace) method access from same namespace (same class)
--FILE--
<?php

namespace App\Services {
class UserService {
private(namespace) function validate(): string {
return "validated";
}

public function process(): string {
return $this->validate();
}
}

$service = new UserService();
echo $service->process() . "\n";
}

?>
--EXPECT--
validated
26 changes: 26 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_basic_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
private(namespace) method access from same namespace (different class)
--FILE--
<?php

namespace App\Services {
class UserService {
private(namespace) function validate(): string {
return "validated";
}
}

class AuthService {
public function authenticate(): string {
$service = new UserService();
return $service->validate();
}
}

$auth = new AuthService();
echo $auth->authenticate() . "\n";
}

?>
--EXPECT--
validated
32 changes: 32 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_basic_003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
private(namespace) method access from different namespace fails
--FILE--
<?php

namespace App\Services {
class UserService {
private(namespace) function validate(): string {
return "validated";
}
}
}

namespace App\Controllers {
class UserController {
public function process(): void {
$service = new \App\Services\UserService();
$service->validate();
}
}

$controller = new UserController();
$controller->process();
}

?>
--EXPECTF--
Fatal error: Uncaught Error: Call to private(namespace) method App\Services\UserService::validate() from scope App\Controllers\UserController in %s:%d
Stack trace:
#0 %s(%d): App\Controllers\UserController->process()
#1 {main}
thrown in %s on line %d
21 changes: 21 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_basic_004.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
private(namespace) property access from same namespace (same class)
--FILE--
<?php

namespace App\Models {
class User {
private(namespace) int $id = 42;

public function getId(): int {
return $this->id;
}
}

$user = new User();
echo $user->getId() . "\n";
}

?>
--EXPECT--
42
24 changes: 24 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_basic_005.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
private(namespace) property access from same namespace (different class)
--FILE--
<?php

namespace App\Models {
class User {
private(namespace) int $id = 42;
}

class UserRepository {
public function getUserId(): int {
$user = new User();
return $user->id;
}
}

$repo = new UserRepository();
echo $repo->getUserId() . "\n";
}

?>
--EXPECT--
42
30 changes: 30 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_basic_006.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--TEST--
private(namespace) property access from different namespace fails
--FILE--
<?php

namespace App\Models {
class User {
private(namespace) int $id = 42;
}
}

namespace App\Controllers {
class UserController {
public function showUserId(): void {
$user = new \App\Models\User();
echo $user->id;
}
}

$controller = new UserController();
$controller->showUserId();
}

?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot access private(namespace) property App\Models\User::$id from scope App\Controllers\UserController in %s:%d
Stack trace:
#0 %s(%d): App\Controllers\UserController->showUserId()
#1 {main}
thrown in %s on line %d
32 changes: 32 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_basic_007.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
private(namespace) access from sub-namespace fails (exact namespace match required)
--FILE--
<?php

namespace App {
class Service {
private(namespace) function test(): string {
return "success";
}
}
}

namespace App\Sub {
class Consumer {
public function callTest(): void {
$service = new \App\Service();
$service->test();
}
}

$consumer = new Consumer();
$consumer->callTest();
}

?>
--EXPECTF--
Fatal error: Uncaught Error: Call to private(namespace) method App\Service::test() from scope App\Sub\Consumer in %s:%d
Stack trace:
#0 %s(%d): App\Sub\Consumer->callTest()
#1 {main}
thrown in %s on line %d
32 changes: 32 additions & 0 deletions Zend/tests/access_modifiers/private_namespace_basic_008.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
private(namespace) access from parent namespace fails (exact namespace match required)
--FILE--
<?php

namespace App\Services\Auth {
class AuthService {
private(namespace) function authenticate(): string {
return "authenticated";
}
}
}

namespace App\Services {
class Consumer {
public function doAuth(): void {
$auth = new Auth\AuthService();
$auth->authenticate();
}
}

$consumer = new Consumer();
$consumer->doAuth();
}

?>
--EXPECTF--
Fatal error: Uncaught Error: Call to private(namespace) method App\Services\Auth\AuthService::authenticate() from scope App\Services\Consumer in %s:%d
Stack trace:
#0 %s(%d): App\Services\Consumer->doAuth()
#1 {main}
thrown in %s on line %d
Loading