Skip to content
This repository was archived by the owner on Jun 1, 2022. It is now read-only.

Commit 59f5283

Browse files
committed
Fix reading records at end of the database when using shared mem
1 parent afa4597 commit 59f5283

File tree

5 files changed

+48
-11
lines changed

5 files changed

+48
-11
lines changed

ChangeLog.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Change Log #
22

3+
## 1.17 (2016-05-16)
4+
5+
* Previously data records at the end of the database were incorrectly returned
6+
as `null` values when using shared memory. This was due to attempting to
7+
read beyond the end of the database. This bug only affected users using
8+
`GEOIP_SHARED_MEMORY`.
9+
310
## 1.16 (2016-01-29)
411

512
* Fixed issue that could cause a notice about using a property on a non-object

src/geoip.inc

+18-10
Original file line numberDiff line numberDiff line change
@@ -1397,12 +1397,12 @@ function _setup_segments($gi)
13971397
$gi->databaseType = GEOIP_COUNTRY_EDITION;
13981398
$gi->record_length = STANDARD_RECORD_LENGTH;
13991399
if ($gi->flags & GEOIP_SHARED_MEMORY) {
1400-
$offset = @shmop_size($gi->shmid) - 3;
1400+
$offset = shmop_size($gi->shmid) - 3;
14011401
for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
1402-
$delim = @shmop_read($gi->shmid, $offset, 3);
1402+
$delim = shmop_read($gi->shmid, $offset, 3);
14031403
$offset += 3;
14041404
if ($delim == (chr(255) . chr(255) . chr(255))) {
1405-
$gi->databaseType = ord(@shmop_read($gi->shmid, $offset, 1));
1405+
$gi->databaseType = ord(shmop_read($gi->shmid, $offset, 1));
14061406
if ($gi->databaseType >= 106) {
14071407
$gi->databaseType -= 105;
14081408
}
@@ -1432,7 +1432,7 @@ function _setup_segments($gi)
14321432
|| ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)
14331433
) {
14341434
$gi->databaseSegments = 0;
1435-
$buf = @shmop_read($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
1435+
$buf = shmop_read($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
14361436
for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
14371437
$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
14381438
}
@@ -1494,6 +1494,7 @@ function _setup_segments($gi)
14941494
|| ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)
14951495
) {
14961496
$gi->databaseSegments = 0;
1497+
14971498
$buf = fread($gi->filehandle, SEGMENT_RECORD_LENGTH);
14981499
for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
14991500
$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
@@ -1525,12 +1526,20 @@ function _setup_segments($gi)
15251526
return $gi;
15261527
}
15271528

1529+
# This should be only used for variable-length records where
1530+
# $start + $maxLength may be greater than the shared mem size
1531+
function _sharedMemRead($gi, $start, $maxLength)
1532+
{
1533+
$readLength = min(shmop_size($gi->shmid) - $start, $maxLength);
1534+
return shmop_read($gi->shmid, $start, $readLength);
1535+
}
1536+
15281537
function geoip_open($filename, $flags)
15291538
{
15301539
$gi = new GeoIP;
15311540
$gi->flags = $flags;
15321541
if ($gi->flags & GEOIP_SHARED_MEMORY) {
1533-
$gi->shmid = @shmop_open(GEOIP_SHM_KEY, "a", 0, 0);
1542+
$gi->shmid = shmop_open(GEOIP_SHM_KEY, "a", 0, 0);
15341543
} else {
15351544
$gi->filehandle = fopen($filename, "rb") or trigger_error("GeoIP API: Can not open $filename\n", E_USER_ERROR);
15361545
if ($gi->flags & GEOIP_MEMORY_CACHE) {
@@ -1686,8 +1695,7 @@ function _geoip_seek_country_v6($gi, $ipnum)
16861695
2 * $gi->record_length
16871696
);
16881697
} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
1689-
$buf = @shmop_read(
1690-
$gi->shmid,
1698+
$buf = _sharedMemRead($gi,
16911699
2 * $gi->record_length * $offset,
16921700
2 * $gi->record_length
16931701
);
@@ -1733,8 +1741,8 @@ function _geoip_seek_country($gi, $ipnum)
17331741
2 * $gi->record_length
17341742
);
17351743
} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
1736-
$buf = @shmop_read(
1737-
$gi->shmid,
1744+
$buf = _sharedMemRead(
1745+
$gi,
17381746
2 * $gi->record_length * $offset,
17391747
2 * $gi->record_length
17401748
);
@@ -1769,7 +1777,7 @@ function _common_get_org($gi, $seek_org)
17691777
{
17701778
$record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
17711779
if ($gi->flags & GEOIP_SHARED_MEMORY) {
1772-
$org_buf = @shmop_read($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
1780+
$org_buf = _sharedMemRead($gi, $record_pointer, MAX_ORG_RECORD_LENGTH);
17731781
} else {
17741782
fseek($gi->filehandle, $record_pointer, SEEK_SET);
17751783
$org_buf = fread($gi->filehandle, MAX_ORG_RECORD_LENGTH);

src/geoipcity.inc

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function _common_get_record($gi, $seek_country)
6565
if ($gi->flags & GEOIP_MEMORY_CACHE) {
6666
$record_buf = substr($gi->memory_buffer, $record_pointer, FULL_RECORD_LENGTH);
6767
} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
68-
$record_buf = @shmop_read($gi->shmid, $record_pointer, FULL_RECORD_LENGTH);
68+
$record_buf = _sharedMemRead($gi, $record_pointer, FULL_RECORD_LENGTH);
6969
} else {
7070
fseek($gi->filehandle, $record_pointer, SEEK_SET);
7171
$record_buf = fread($gi->filehandle, FULL_RECORD_LENGTH);

tests/CityTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,14 @@ public function testCity()
3636
geoip_country_code_by_addr($gi, "64.17.254.216")
3737
);
3838
}
39+
40+
public function testCityWithSharedMemory()
41+
{
42+
geoip_load_shared_mem("tests/data/GeoIPCity.dat");
43+
44+
$gi = geoip_open("tests/data/GeoIPCity.dat", GEOIP_SHARED_MEMORY);
45+
$record = geoip_record_by_addr($gi, "222.230.136.0");
46+
47+
$this->assertEquals('Setagaya', $record->city);
48+
}
3949
}

tests/NetspeedcellTest.php

+12
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,16 @@ public function testNetspeedcell()
1111
geoip_org_by_addr($gi, "2.125.160.1")
1212
);
1313
}
14+
15+
public function testNetspeedcellWithSharedMemory()
16+
{
17+
geoip_load_shared_mem("tests/data/GeoIPNetSpeedCell.dat");
18+
19+
$gi = geoip_open("tests/data/GeoIPNetSpeedCell.dat", GEOIP_SHARED_MEMORY);
20+
21+
$this->assertEquals(
22+
'Dialup',
23+
geoip_name_by_addr($gi, "2.125.160.1")
24+
);
25+
}
1426
}

0 commit comments

Comments
 (0)