Skip to content

Commit 5eb1c54

Browse files
committed
grammars can escape values for safe embedding in sql queries
1 parent 7046e9b commit 5eb1c54

File tree

6 files changed

+82
-9
lines changed

6 files changed

+82
-9
lines changed

src/Illuminate/Database/Connection.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,10 @@ public function useDefaultQueryGrammar()
257257
*/
258258
protected function getDefaultQueryGrammar()
259259
{
260-
return new QueryGrammar;
260+
$grammar = new QueryGrammar();
261+
$grammar->setConnection($this);
262+
263+
return $grammar;
261264
}
262265

263266
/**

src/Illuminate/Database/Grammar.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ abstract class Grammar
1010
{
1111
use Macroable;
1212

13+
/**
14+
* The connection used for escaping values.
15+
*
16+
* @var \Illuminate\Database\Connection
17+
*/
18+
protected $connection = null;
19+
1320
/**
1421
* The grammar table prefix.
1522
*
@@ -196,6 +203,32 @@ public function quoteString($value)
196203
return "'$value'";
197204
}
198205

206+
/**
207+
* Escapes a value to use it for safe SQL embedding.
208+
*
209+
* @param string|float|int $value
210+
* @return string
211+
*/
212+
public function escape($value)
213+
{
214+
if (null === $this->connection) {
215+
throw new RuntimeException('The grammar has no connection to escape any value.');
216+
}
217+
218+
// The documentation of PDO::quote states that it should be theoretically safe to use a quoted string within
219+
// a SQL query. While only being "theoretically" safe this behaviour is used within the PHP MySQL driver all the
220+
// time as no real prepared statements are used because it is emulating prepares by default. All remaining known
221+
// SQL injections are always some strange charset conversion tricks that start by using invalid UTF-8 sequences.
222+
// But those attacks are fixed by setting the proper connection charset which is done by the standard Laravel
223+
// configuration. To further secure the implementation we can scrub the value by checking for invalid UTF-8
224+
// sequences.
225+
if (false === preg_match('//u', (string) $value)) {
226+
throw new RuntimeException('The value contains an invalid UTF-8 byte sequence.');
227+
}
228+
229+
return $this->connection->getReadPdo()->quote($value);
230+
}
231+
199232
/**
200233
* Determine if the given value is a raw expression.
201234
*
@@ -254,4 +287,17 @@ public function setTablePrefix($prefix)
254287

255288
return $this;
256289
}
290+
291+
/**
292+
* Set the grammar's database connection.
293+
*
294+
* @param \Illuminate\Database\Connection $prefix
295+
* @return $this
296+
*/
297+
public function setConnection($connection)
298+
{
299+
$this->connection = $connection;
300+
301+
return $this;
302+
}
257303
}

src/Illuminate/Database/MySqlConnection.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public function isMaria()
3030
*/
3131
protected function getDefaultQueryGrammar()
3232
{
33-
return $this->withTablePrefix(new QueryGrammar);
33+
$grammar = new QueryGrammar();
34+
$grammar->setConnection($this);
35+
36+
return $this->withTablePrefix($grammar);
3437
}
3538

3639
/**
@@ -54,7 +57,10 @@ public function getSchemaBuilder()
5457
*/
5558
protected function getDefaultSchemaGrammar()
5659
{
57-
return $this->withTablePrefix(new SchemaGrammar);
60+
$grammar = new SchemaGrammar();
61+
$grammar->setConnection($this);
62+
63+
return $this->withTablePrefix($grammar);
5864
}
5965

6066
/**

src/Illuminate/Database/PostgresConnection.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ class PostgresConnection extends Connection
1919
*/
2020
protected function getDefaultQueryGrammar()
2121
{
22-
return $this->withTablePrefix(new QueryGrammar);
22+
$grammar = new QueryGrammar();
23+
$grammar->setConnection($this);
24+
25+
return $this->withTablePrefix($grammar);
2326
}
2427

2528
/**
@@ -43,7 +46,10 @@ public function getSchemaBuilder()
4346
*/
4447
protected function getDefaultSchemaGrammar()
4548
{
46-
return $this->withTablePrefix(new SchemaGrammar);
49+
$grammar = new SchemaGrammar();
50+
$grammar->setConnection($this);
51+
52+
return $this->withTablePrefix($grammar);
4753
}
4854

4955
/**

src/Illuminate/Database/SQLiteConnection.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ public function __construct($pdo, $database = '', $tablePrefix = '', array $conf
4343
*/
4444
protected function getDefaultQueryGrammar()
4545
{
46-
return $this->withTablePrefix(new QueryGrammar);
46+
$grammar = new QueryGrammar();
47+
$grammar->setConnection($this);
48+
49+
return $this->withTablePrefix($grammar);
4750
}
4851

4952
/**
@@ -67,7 +70,10 @@ public function getSchemaBuilder()
6770
*/
6871
protected function getDefaultSchemaGrammar()
6972
{
70-
return $this->withTablePrefix(new SchemaGrammar);
73+
$grammar = new SchemaGrammar();
74+
$grammar->setConnection($this);
75+
76+
return $this->withTablePrefix($grammar);
7177
}
7278

7379
/**

src/Illuminate/Database/SqlServerConnection.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ public function transaction(Closure $callback, $attempts = 1)
6161
*/
6262
protected function getDefaultQueryGrammar()
6363
{
64-
return $this->withTablePrefix(new QueryGrammar);
64+
$grammar = new QueryGrammar();
65+
$grammar->setConnection($this);
66+
67+
return $this->withTablePrefix($grammar);
6568
}
6669

6770
/**
@@ -85,7 +88,10 @@ public function getSchemaBuilder()
8588
*/
8689
protected function getDefaultSchemaGrammar()
8790
{
88-
return $this->withTablePrefix(new SchemaGrammar);
91+
$grammar = new SchemaGrammar();
92+
$grammar->setConnection($this);
93+
94+
return $this->withTablePrefix($grammar);
8995
}
9096

9197
/**

0 commit comments

Comments
 (0)