Skip to content

Commit 5eff125

Browse files
committed
Guard against invalid user input
1 parent e7c1cd7 commit 5eff125

2 files changed

Lines changed: 56 additions & 21 deletions

File tree

src/Connection.php

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Doctrine\DBAL\SQL\Parser;
3434
use Doctrine\DBAL\Types\Type;
3535
use Doctrine\Deprecations\Deprecation;
36+
use Exception;
3637
use InvalidArgumentException;
3738
use SensitiveParameter;
3839
use Throwable;
@@ -523,44 +524,52 @@ public function insert(string $table, array $data, array $types = []): int|strin
523524
* Inserts multiple table rows with specified data.
524525
*
525526
* Table expression and columns are not escaped and are not safe for user-input.
526-
* Each array within data should have the same keys.
527+
* Each row should have the same keys
527528
*
528-
* @param array<array<string, mixed>> $data
529-
* @param array<int<0,max>, string|ParameterType|Type>|array<string, string|ParameterType|Type> $types
529+
* @param array<array<string, mixed>> $rows
530+
* @param array<string, string|ParameterType|Type> $types
530531
*
531532
* @return int|numeric-string The number of affected rows.
532533
*
533534
* @throws Exception
534535
*/
535-
public function insertMany(string $table, array $data, array $types = []): int|string
536+
public function insertMany(string $table, array $rows, array $types = []): int|string
536537
{
537-
$numRows = count($data);
538+
$numRows = count($rows);
538539
if ($numRows === 0) {
539-
return $this->executeStatement('INSERT INTO ' . $table . ' () VALUES ()');
540+
return 0;
540541
}
541542

542543
$columns = [];
543544
$values = [];
544545
$set = [];
545546

546-
$first = true;
547-
foreach ($data as $row) {
547+
$first = true;
548+
$columnCount = 0;
549+
foreach ($rows as $row) {
548550
if ($first) {
549-
$first = false;
550-
$columns = array_keys($row);
551-
$set = array_fill(0, count($columns), '?');
551+
$first = false;
552+
$columns = array_keys($row);
553+
$columnCount = count($columns);
554+
$set = array_fill(0, count($columns), '?');
555+
}
556+
557+
if ($columnCount !== count($row)) {
558+
// TODO: add a custom exception
559+
throw new Exception('Column count mismatch');
552560
}
553561

554562
foreach ($columns as $column) {
555-
$values[] = $row[$column];
563+
// TODO: add a custom exception
564+
$values[] = $row[$column] ?? throw new Exception('Column ' . $column . ' does not exist');
556565
}
557566
}
558567

559568
$setParams = '(' . implode(',', $set) . ')';
560569

561-
$calculatedTypes = is_string(key($types))
570+
$calculatedTypes = $types
562571
? $this->extractTypeValues($columns, $types)
563-
: array_merge($types, array_fill(0, count($columns) - count($types), ParameterType::STRING));
572+
: [];
564573

565574
return $this->executeStatement(
566575
'INSERT INTO ' . $table . ' (' . implode(', ', $columns) . ') VALUES '

tests/ConnectionTest.php

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,38 @@ public function testInsertManySpecifyingFirstKeyOnly(): void
405405
],
406406

407407
],
408-
['integer'],
408+
['c1' => 'integer'],
409+
);
410+
}
411+
412+
public function testInsertManyWithEmptyValues(): void
413+
{
414+
$conn = $this->getExecuteStatementMockConnection();
415+
416+
$conn->expects(self::once())
417+
->method('executeStatement')
418+
->with(
419+
'INSERT INTO footable () VALUES (), ()',
420+
[],
421+
[],
422+
);
423+
424+
$conn->insertMany(
425+
'footable',
426+
[[], []],
427+
);
428+
}
429+
430+
public function testInsertManyWithNoValues(): void
431+
{
432+
$conn = $this->getExecuteStatementMockConnection();
433+
434+
$conn->expects(self::never())
435+
->method('executeStatement');
436+
437+
$conn->insertMany(
438+
'footable',
439+
[],
409440
);
410441
}
411442

@@ -423,12 +454,7 @@ public function testInsertManyWithoutTypes(): void
423454
1,
424455
'i2-c2',
425456
],
426-
[
427-
ParameterType::STRING,
428-
ParameterType::STRING,
429-
ParameterType::STRING,
430-
ParameterType::STRING,
431-
],
457+
[],
432458
);
433459

434460
$conn->insertMany(

0 commit comments

Comments
 (0)