4
0

UserDAOTest.php 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. <?php
  2. declare(strict_types=1);
  3. use PHPUnit\Framework\Attributes\DataProvider;
  4. use PHPUnit\Framework\TestCase;
  5. class UserDAOTest extends TestCase {
  6. #[DataProvider('pathTraversalPayloadsProvider')]
  7. public function testExistsRejectsPathTraversal(string $payload): void {
  8. self::assertFalse(FreshRSS_UserDAO::exists($payload));
  9. }
  10. #[DataProvider('pathTraversalPayloadsProvider')]
  11. public function testMtimeRejectsPathTraversal(string $payload): void {
  12. self::assertSame(0, FreshRSS_UserDAO::mtime($payload));
  13. }
  14. #[DataProvider('pathTraversalPayloadsProvider')]
  15. public function testCtimeRejectsPathTraversal(string $payload): void {
  16. self::assertSame(0, FreshRSS_UserDAO::ctime($payload));
  17. }
  18. /**
  19. * @return array<string,array<int,string>>
  20. */
  21. public static function pathTraversalPayloadsProvider(): array {
  22. return [
  23. 'parent directory' => ['../'],
  24. 'double parent directory' => ['../../'],
  25. 'traversal to app' => ['../../app'],
  26. 'traversal to etc' => ['../../../etc'],
  27. 'traversal with null byte' => ["../\0"],
  28. 'absolute path' => ['/etc/passwd'],
  29. 'dot only' => ['.'],
  30. 'double dot' => ['..'],
  31. 'slash in name' => ['user/config'],
  32. 'backslash traversal' => ['..\\..\\app'],
  33. 'encoded traversal' => ['%2e%2e%2f'],
  34. 'mixed traversal' => ['valid/../invalid'],
  35. 'empty string' => [''],
  36. ];
  37. }
  38. #[DataProvider('validUsernamesProvider')]
  39. public function testExistsAcceptsValidUsernames(string $username): void {
  40. $result = FreshRSS_UserDAO::exists($username);
  41. self::assertIsBool($result);
  42. }
  43. #[DataProvider('validUsernamesProvider')]
  44. public function testMtimeAcceptsValidUsernames(string $username): void {
  45. $result = FreshRSS_UserDAO::mtime($username);
  46. self::assertIsInt($result);
  47. }
  48. #[DataProvider('validUsernamesProvider')]
  49. public function testCtimeAcceptsValidUsernames(string $username): void {
  50. $result = FreshRSS_UserDAO::ctime($username);
  51. self::assertIsInt($result);
  52. }
  53. /**
  54. * @return array<string,array<int,string>>
  55. */
  56. public static function validUsernamesProvider(): array {
  57. return [
  58. 'simple' => ['alice'],
  59. 'with numbers' => ['user123'],
  60. 'with underscore' => ['test_user'],
  61. 'with dot' => ['user.name'],
  62. 'with hyphen' => ['user-name'],
  63. 'with at' => ['user@domain'],
  64. 'single char' => ['a'],
  65. 'max length' => [str_repeat('a', 39)],
  66. ];
  67. }
  68. }