Skip to content
This repository was archived by the owner on Jun 2, 2025. It is now read-only.

Commit 99c0350

Browse files
committed
Disallow accessing object with reserved prefix
1 parent 0690f44 commit 99c0350

File tree

2 files changed

+65
-4
lines changed

2 files changed

+65
-4
lines changed

tests/WP_SQLite_Driver_Tests.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3893,4 +3893,42 @@ public function testCompoundPrimaryKeyAndAutoincrementNotSupported(): void {
38933893
'CREATE TABLE t1 (id1 INT AUTO_INCREMENT, id2 INT, PRIMARY KEY(id1, id2))'
38943894
);
38953895
}
3896+
3897+
/**
3898+
* @dataProvider getReservedPrefixTestData
3899+
*/
3900+
public function testReservedPrefix( string $query, string $error ): void {
3901+
$this->expectException( WP_SQLite_Driver_Exception::class );
3902+
$this->expectExceptionMessage( $error );
3903+
$this->assertQuery( $query );
3904+
}
3905+
3906+
public function getReservedPrefixTestData(): array {
3907+
return array(
3908+
array(
3909+
'SELECT * FROM _wp_sqlite_t',
3910+
"Invalid identifier `_wp_sqlite_t`, prefix '_wp_sqlite_' is reserved",
3911+
),
3912+
array(
3913+
'SELECT _wp_sqlite_t FROM t',
3914+
"Invalid identifier `_wp_sqlite_t`, prefix '_wp_sqlite_' is reserved",
3915+
),
3916+
array(
3917+
'SELECT t._wp_sqlite_t FROM t',
3918+
"Invalid identifier `t`.`_wp_sqlite_t`, prefix '_wp_sqlite_' is reserved",
3919+
),
3920+
array(
3921+
'CREATE TABLE _wp_sqlite_t (id INT)',
3922+
"Invalid identifier `_wp_sqlite_t`, prefix '_wp_sqlite_' is reserved",
3923+
),
3924+
array(
3925+
'ALTER TABLE _wp_sqlite_t ADD COLUMN name TEXT',
3926+
"Invalid identifier `_wp_sqlite_t`, prefix '_wp_sqlite_' is reserved",
3927+
),
3928+
array(
3929+
'DROP TABLE _wp_sqlite_t',
3930+
"Invalid identifier `_wp_sqlite_t`, prefix '_wp_sqlite_' is reserved",
3931+
),
3932+
);
3933+
}
38963934
}

wp-includes/sqlite-ast/class-wp-sqlite-driver.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,7 +2060,8 @@ private function translate_qualified_identifier(
20602060
?WP_Parser_Node $object_node = null,
20612061
?WP_Parser_Node $child_node = null
20622062
): string {
2063-
$parts = array();
2063+
$parts = array();
2064+
$uses_reserved_prefix = false;
20642065

20652066
// Database name.
20662067
$is_information_schema = 'information_schema' === $this->db_name;
@@ -2091,16 +2092,38 @@ private function translate_qualified_identifier(
20912092
);
20922093
$parts[] = $this->information_schema_builder->get_table_name( $object_name );
20932094
} else {
2094-
$parts[] = $this->translate( $object_node );
2095+
$quoted_object_name = $this->translate( $object_node );
2096+
$object_name = $this->unquote_sqlite_identifier( $quoted_object_name );
2097+
if ( str_starts_with( $object_name, self::RESERVED_PREFIX ) ) {
2098+
$uses_reserved_prefix = true;
2099+
}
2100+
$parts[] = $quoted_object_name;
20952101
}
20962102
}
20972103

20982104
// Object child name (column, index, etc.).
20992105
if ( null !== $child_node ) {
2100-
$parts[] = $this->translate( $child_node );
2106+
$quoted_object_name = $this->translate( $child_node );
2107+
$object_name = $this->unquote_sqlite_identifier( $quoted_object_name );
2108+
if ( str_starts_with( $object_name, self::RESERVED_PREFIX ) ) {
2109+
$uses_reserved_prefix = true;
2110+
}
2111+
$parts[] = $quoted_object_name;
2112+
}
2113+
2114+
$identifier = implode( '.', $parts );
2115+
2116+
if ( true === $uses_reserved_prefix ) {
2117+
throw $this->new_driver_exception(
2118+
sprintf(
2119+
"Invalid identifier %s, prefix '%s' is reserved",
2120+
$identifier,
2121+
self::RESERVED_PREFIX
2122+
)
2123+
);
21012124
}
21022125

2103-
return implode( '.', $parts );
2126+
return $identifier;
21042127
}
21052128

21062129
/**

0 commit comments

Comments
 (0)