Skip to content

Commit 2096d3f

Browse files
committed
Clamp limit values to be unsigned integers.
This solves large page numbers potentially turning into scientific notation when being formatted into queries. It also further safeguards against SQL manipulation. Refs #GH-1263
1 parent bd3be28 commit 2096d3f

File tree

4 files changed

+36
-25
lines changed

4 files changed

+36
-25
lines changed

lib/Cake/Controller/Component/PaginatorComponent.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ public function paginate($object = null, $scope = array(), $whitelist = array())
212212
$pageCount = intval(ceil($count / $limit));
213213
$requestedPage = $page;
214214
$page = max(min($page, $pageCount), 1);
215+
if ($requestedPage > $page) {
216+
throw new NotFoundException();
217+
}
215218

216219
$paging = array(
217220
'page' => $page,
@@ -234,10 +237,6 @@ public function paginate($object = null, $scope = array(), $whitelist = array())
234237
array($object->alias => $paging)
235238
);
236239

237-
if ($requestedPage > $page) {
238-
throw new NotFoundException();
239-
}
240-
241240
if (
242241
!in_array('Paginator', $this->Controller->helpers) &&
243242
!array_key_exists('Paginator', $this->Controller->helpers)

lib/Cake/Model/Datasource/DboSource.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2672,16 +2672,13 @@ protected function _quoteMatchedField($match) {
26722672
*/
26732673
public function limit($limit, $offset = null) {
26742674
if ($limit) {
2675-
$rt = '';
2676-
if (!strpos(strtolower($limit), 'limit')) {
2677-
$rt = ' LIMIT';
2678-
}
2675+
$rt = ' LIMIT';
26792676

26802677
if ($offset) {
2681-
$rt .= ' ' . $offset . ',';
2678+
$rt .= sprintf(' %u,', $offset);
26822679
}
26832680

2684-
$rt .= ' ' . $limit;
2681+
$rt .= sprintf(' %u', $limit);
26852682
return $rt;
26862683
}
26872684
return null;

lib/Cake/Test/Case/Controller/Component/PaginatorComponentTest.php

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -896,44 +896,35 @@ public function testOutOfRangePageNumberGetsClamped() {
896896
* @expectedException NotFoundException
897897
* @return void
898898
*/
899-
public function testOutOfVeryBigRangePageNumberGetsClamped() {
899+
public function testOutOfVeryBigPageNumberGetsClamped() {
900900
$Controller = new PaginatorTestController($this->request);
901901
$Controller->uses = array('PaginatorControllerPost');
902902
$Controller->params['named'] = array(
903-
'page' => 3000000000000000000000000,
903+
'page' => '3000000000000000000000000',
904904
);
905905
$Controller->constructClasses();
906906
$Controller->PaginatorControllerPost->recursive = 0;
907907
$Controller->Paginator->paginate('PaginatorControllerPost');
908-
}
908+
}
909909

910910
/**
911911
* testOutOfRangePageNumberAndPageCountZero
912912
*
913+
* @expectedException NotFoundException
913914
* @return void
914915
*/
915916
public function testOutOfRangePageNumberAndPageCountZero() {
916917
$Controller = new PaginatorTestController($this->request);
917918
$Controller->uses = array('PaginatorControllerPost');
918919
$Controller->params['named'] = array(
919-
'page' => 3000,
920+
'page' => '3000',
920921
);
921922
$Controller->constructClasses();
922923
$Controller->PaginatorControllerPost->recursive = 0;
923924
$Controller->paginate = array(
924925
'conditions' => array('PaginatorControllerPost.id >' => 100)
925926
);
926-
try {
927-
$Controller->Paginator->paginate('PaginatorControllerPost');
928-
} catch (NotFoundException $e) {
929-
$this->assertEquals(
930-
1,
931-
$Controller->request->params['paging']['PaginatorControllerPost']['page'],
932-
'Page number should not be 0'
933-
);
934-
return;
935-
}
936-
$this->fail();
927+
$Controller->Paginator->paginate('PaginatorControllerPost');
937928
}
938929

939930
/**

lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,4 +1229,28 @@ public function testConditionKeysToStringVirtualField() {
12291229
$this->assertEquals($expected, $result[0]);
12301230
}
12311231

1232+
/**
1233+
* Test the limit function.
1234+
*
1235+
* @return void
1236+
*/
1237+
public function testLimit() {
1238+
$db = new DboTestSource;
1239+
1240+
$result = $db->limit('0');
1241+
$this->assertNull($result);
1242+
1243+
$result = $db->limit('10');
1244+
$this->assertEquals(' LIMIT 10', $result);
1245+
1246+
$result = $db->limit('FARTS', 'BOOGERS');
1247+
$this->assertEquals(' LIMIT 0, 0', $result);
1248+
1249+
$result = $db->limit(20, 10);
1250+
$this->assertEquals(' LIMIT 10, 20', $result);
1251+
1252+
$result = $db->limit(10, 300000000000000000000000000000);
1253+
$this->assertEquals(' LIMIT 0, 10', $result);
1254+
}
1255+
12321256
}

0 commit comments

Comments
 (0)