@@ -454,7 +454,7 @@ public function providerRouteMatching(): array
454454 /**
455455 * @dataProvider providerRouteMatching
456456 */
457- public function testCanMatchRoute (string $ method , string $ path , string $ url = null ): void
457+ public function testCanMatchRoute (string $ method , string $ path , ? string $ url = null ): void
458458 {
459459 $ url ??= $ path ;
460460 $ expected = null ;
@@ -616,4 +616,61 @@ public function testWildcardRoute(): void
616616 $ _SERVER ['REQUEST_METHOD ' ] = $ method ;
617617 $ _SERVER ['REQUEST_URI ' ] = $ uri ;
618618 }
619+
620+ public function testCallableStringParametersNotExecuted (): void
621+ {
622+ // Test that callable strings (like function names) are not executed
623+ $ route = new Route ('GET ' , '/test-callable-string ' );
624+
625+ $ route
626+ ->param ('callback ' , 'phpinfo ' , new Text (200 ), 'callback param ' , true )
627+ ->action (function ($ callback ) {
628+ // If the string 'phpinfo' was executed as a function,
629+ // it would output PHP info. Instead, it should just be the string.
630+ echo 'callback-value: ' . $ callback ;
631+ });
632+
633+ \ob_start ();
634+ $ this ->http ->execute ($ route , new Request (), '1 ' );
635+ $ result = \ob_get_contents ();
636+ \ob_end_clean ();
637+
638+ $ this ->assertEquals ('callback-value: phpinfo ' , $ result );
639+
640+ // Test with request parameter that is a callable string
641+ $ route2 = new Route ('GET ' , '/test-callable-string-param ' );
642+
643+ $ route2
644+ ->param ('func ' , 'default ' , new Text (200 ), 'func param ' , false )
645+ ->action (function ($ func ) {
646+ echo 'func-value: ' . $ func ;
647+ });
648+
649+ \ob_start ();
650+ $ request = new UtopiaFPMRequestTest ();
651+ $ request ::_setParams (['func ' => 'system ' ]);
652+ $ this ->http ->execute ($ route2 , $ request , '1 ' );
653+ $ result = \ob_get_contents ();
654+ \ob_end_clean ();
655+
656+ $ this ->assertEquals ('func-value: system ' , $ result );
657+
658+ // Test callable closure still works
659+ $ route3 = new Route ('GET ' , '/test-callable-closure ' );
660+
661+ $ route3
662+ ->param ('generated ' , function () {
663+ return 'generated-value ' ;
664+ }, new Text (200 ), 'generated param ' , true )
665+ ->action (function ($ generated ) {
666+ echo 'generated: ' . $ generated ;
667+ });
668+
669+ \ob_start ();
670+ $ this ->http ->execute ($ route3 , new Request (), '1 ' );
671+ $ result = \ob_get_contents ();
672+ \ob_end_clean ();
673+
674+ $ this ->assertEquals ('generated: generated-value ' , $ result );
675+ }
619676}
0 commit comments