From 99b4f7c16886803c0af5e0b5862d85ad6dac95f7 Mon Sep 17 00:00:00 2001 From: Serge Latyntcev Date: Mon, 1 Jul 2019 10:27:09 +1200 Subject: [PATCH] FIX DatabaseStore binary safety --- src/Store/DatabaseStore.php | 48 +++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/Store/DatabaseStore.php b/src/Store/DatabaseStore.php index fdb1536..4563df2 100644 --- a/src/Store/DatabaseStore.php +++ b/src/Store/DatabaseStore.php @@ -61,7 +61,8 @@ public function read($session_id) if ($result && $result->numRecords()) { $data = $result->first(); - return $data['Data']; + $decoded = $this->binaryDataJsonDecode($data['Data']); + return is_null($decoded) ? $data['Data'] : $decoded; } } @@ -79,7 +80,7 @@ public function write($session_id, $session_data) ON DUPLICATE KEY UPDATE "Expiry" = %2$u, "Data" = \'%3$s\'', Convert::raw2sql($session_id), $expiry, - Convert::raw2sql($session_data) + Convert::raw2sql($this->binaryDataJsonEncode($session_data)) )); return true; @@ -101,4 +102,47 @@ public function gc($maxlifetime) $this->getNow() )); } + + /** + * Encode binary data into ASCII string (a subset of UTF-8) + * + * Silverstripe <= 4.4 does not have a binary db field implementation, so we have to store + * binary data as text + * + * @param string $data This is a binary blob + * + * @return string + */ + private function binaryDataJsonEncode($data) + { + return json_encode([ + self::class, + base64_encode($data) + ]); + } + + /** + * Decode ASCII string into original binary data (a php string) + * + * Silverstripe <= 4.4 does not have a binary db field implementation, so we have to store + * binary data as text + * + * @param string $text + * + * @param null|string + */ + private function binaryDataJsonDecode($text) + { + $struct = json_decode($text, true, 2); + + if (!is_array($struct) || count($struct) !== 2) { + return null; + } + + if (!isset($struct[0]) || !isset($struct[1]) || $struct[0] !== self::class) { + return null; + } + + return base64_decode($struct[1]); + } }