@@ -1808,16 +1808,34 @@ private function translate_string_literal( WP_Parser_Node $node ): string {
18081808 }
18091809
18101810 /*
1811- * 6. Remove null characters.
1811+ * 6. Handle null characters.
18121812 *
1813- * SQLite doesn't support null characters in strings.
1814- */
1815- $ value = str_replace ( "\0" , '' , $ value );
1816-
1817- /*
1818- * 7. Escape and add quotes.
1813+ * SQLite doesn't fully support null characters (\u0000) in strings.
1814+ * However, it can store them and read them, with some limitations.
1815+ *
1816+ * In PHP, null bytes are often produced by the serialize() function.
1817+ * Removing them would damage the serialized data.
1818+ *
1819+ * There is no way to store null bytes using a string literal, so we
1820+ * need to split the string and concatenate null bytes with its parts.
1821+ * This will convert literals will null bytes to expressions.
1822+ *
1823+ * Alternatively, we could replace string literals with parameters and
1824+ * pass them using prepared statements. However, that's not universally
1825+ * applicable for all string literals (e.g., in default column values).
1826+ *
1827+ * See:
1828+ * https://www.sqlite.org/nulinstr.html
18191829 */
1820- return "' " . str_replace ( "' " , "'' " , $ value ) . "' " ;
1830+ $ parts = array ();
1831+ foreach ( explode ( "\0" , $ value ) as $ segment ) {
1832+ // Escape and quote each segment.
1833+ $ parts [] = "' " . str_replace ( "' " , "'' " , $ segment ) . "' " ;
1834+ }
1835+ if ( count ( $ parts ) > 1 ) {
1836+ return '( ' . implode ( ' || CHAR(0) || ' , $ parts ) . ') ' ;
1837+ }
1838+ return $ parts [0 ];
18211839 }
18221840
18231841 private function translate_pure_identifier ( WP_Parser_Node $ node ): string {
0 commit comments