Skip to content

Commit

Permalink
Detect Gzip and Bzip2 bytes overflow (#39)
Browse files Browse the repository at this point in the history
* calculate overflow bytes in RenderGzipFileStream

* calculate overflow bytes in RenderBzip2FileStream

* update tests
  • Loading branch information
peter-gribanov authored Aug 26, 2019
1 parent 3b13fcc commit ecc5ae0
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/Stream/RenderBzip2FileStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use GpsLab\Component\Sitemap\Render\SitemapRender;
use GpsLab\Component\Sitemap\Stream\Exception\FileAccessException;
use GpsLab\Component\Sitemap\Stream\Exception\LinksOverflowException;
use GpsLab\Component\Sitemap\Stream\Exception\SizeOverflowException;
use GpsLab\Component\Sitemap\Stream\Exception\StreamStateException;
use GpsLab\Component\Sitemap\Stream\State\StreamState;
use GpsLab\Component\Sitemap\Url\Url;
Expand Down Expand Up @@ -53,6 +54,11 @@ class RenderBzip2FileStream implements FileStream
*/
private $end_string = '';

/**
* @var int
*/
private $used_bytes = 0;

/**
* @param SitemapRender $render
* @param string $filename
Expand Down Expand Up @@ -103,6 +109,7 @@ public function close()
$this->handle = null;
$this->tmp_filename = '';
$this->counter = 0;
$this->used_bytes = 0;
}

/**
Expand All @@ -120,6 +127,11 @@ public function push(Url $url)

$render_url = $this->render->url($url);

$expected_bytes = $this->used_bytes + strlen($render_url) + strlen($this->end_string);
if ($expected_bytes > self::BYTE_LIMIT) {
throw SizeOverflowException::withLimit(self::BYTE_LIMIT);
}

$this->write($render_url);
++$this->counter;
}
Expand All @@ -138,5 +150,6 @@ public function count()
private function write($string)
{
bzwrite($this->handle, $string);
$this->used_bytes += strlen($string);
}
}
13 changes: 13 additions & 0 deletions src/Stream/RenderGzipFileStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use GpsLab\Component\Sitemap\Stream\Exception\CompressionLevelException;
use GpsLab\Component\Sitemap\Stream\Exception\FileAccessException;
use GpsLab\Component\Sitemap\Stream\Exception\LinksOverflowException;
use GpsLab\Component\Sitemap\Stream\Exception\SizeOverflowException;
use GpsLab\Component\Sitemap\Stream\Exception\StreamStateException;
use GpsLab\Component\Sitemap\Stream\State\StreamState;
use GpsLab\Component\Sitemap\Url\Url;
Expand Down Expand Up @@ -59,6 +60,11 @@ class RenderGzipFileStream implements FileStream
*/
private $end_string = '';

/**
* @var int
*/
private $used_bytes = 0;

/**
* @param SitemapRender $render
* @param string $filename
Expand Down Expand Up @@ -114,6 +120,7 @@ public function close()
$this->handle = null;
$this->tmp_filename = '';
$this->counter = 0;
$this->used_bytes = 0;
}

/**
Expand All @@ -131,6 +138,11 @@ public function push(Url $url)

$render_url = $this->render->url($url);

$expected_bytes = $this->used_bytes + strlen($render_url) + strlen($this->end_string);
if ($expected_bytes > self::BYTE_LIMIT) {
throw SizeOverflowException::withLimit(self::BYTE_LIMIT);
}

$this->write($render_url);
++$this->counter;
}
Expand All @@ -149,5 +161,6 @@ public function count()
private function write($string)
{
gzwrite($this->handle, $string);
$this->used_bytes += strlen($string);
}
}
33 changes: 33 additions & 0 deletions tests/Stream/RenderBzip2FileStreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use GpsLab\Component\Sitemap\Render\SitemapRender;
use GpsLab\Component\Sitemap\Stream\Exception\LinksOverflowException;
use GpsLab\Component\Sitemap\Stream\Exception\SizeOverflowException;
use GpsLab\Component\Sitemap\Stream\Exception\StreamStateException;
use GpsLab\Component\Sitemap\Stream\RenderBzip2FileStream;
use GpsLab\Component\Sitemap\Url\Url;
Expand Down Expand Up @@ -187,6 +188,38 @@ public function testOverflowLinks()
}
}

public function testOverflowSize()
{
$loops = 10000;
$loop_size = (int) floor(RenderBzip2FileStream::BYTE_LIMIT / $loops);
$prefix_size = RenderBzip2FileStream::BYTE_LIMIT - ($loops * $loop_size);
$prefix_size += 1; // overflow byte
$loc = str_repeat('/', $loop_size);

$this->render
->expects($this->at(0))
->method('start')
->will($this->returnValue(str_repeat('/', $prefix_size)))
;
$this->render
->expects($this->atLeastOnce())
->method('url')
->will($this->returnValue($loc))
;

$this->stream->open();

try {
for ($i = 0; $i < $loops; ++$i) {
$this->stream->push(new Url($loc));
}
$this->assertTrue(false, 'Must throw SizeOverflowException.');
} catch (SizeOverflowException $e) {
$this->stream->close();
file_put_contents($this->filename, ''); // not check content
}
}

public function testReset()
{
$this->open();
Expand Down
33 changes: 33 additions & 0 deletions tests/Stream/RenderGzipFileStreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use GpsLab\Component\Sitemap\Render\SitemapRender;
use GpsLab\Component\Sitemap\Stream\Exception\LinksOverflowException;
use GpsLab\Component\Sitemap\Stream\Exception\SizeOverflowException;
use GpsLab\Component\Sitemap\Stream\Exception\StreamStateException;
use GpsLab\Component\Sitemap\Stream\RenderGzipFileStream;
use GpsLab\Component\Sitemap\Url\Url;
Expand Down Expand Up @@ -211,6 +212,38 @@ public function testOverflowLinks()
}
}

public function testOverflowSize()
{
$loops = 10000;
$loop_size = (int) floor(RenderGzipFileStream::BYTE_LIMIT / $loops);
$prefix_size = RenderGzipFileStream::BYTE_LIMIT - ($loops * $loop_size);
$prefix_size += 1; // overflow byte
$loc = str_repeat('/', $loop_size);

$this->render
->expects($this->at(0))
->method('start')
->will($this->returnValue(str_repeat('/', $prefix_size)))
;
$this->render
->expects($this->atLeastOnce())
->method('url')
->will($this->returnValue($loc))
;

$this->stream->open();

try {
for ($i = 0; $i < $loops; ++$i) {
$this->stream->push(new Url($loc));
}
$this->assertTrue(false, 'Must throw SizeOverflowException.');
} catch (SizeOverflowException $e) {
$this->stream->close();
file_put_contents($this->filename, ''); // not check content
}
}

public function testReset()
{
$this->open();
Expand Down

0 comments on commit ecc5ae0

Please sign in to comment.