aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/Pl_PNGFilter.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2017-12-25 01:18:52 +0100
committerJay Berkenbilt <ejb@ql.org>2017-12-25 20:24:48 +0100
commita3a55be9cdebd517f4dce9ff66aeda78b136b003 (patch)
tree8d2bed12e9d21eb63db79218ad5dc05d33f4bbb9 /libqpdf/Pl_PNGFilter.cc
parent9a487202463c2bf05fc8fce8ae6a1005348a69a0 (diff)
downloadqpdf-a3a55be9cdebd517f4dce9ff66aeda78b136b003.tar.zst
Correct errors in PNG filters and make use from library
Diffstat (limited to 'libqpdf/Pl_PNGFilter.cc')
-rw-r--r--libqpdf/Pl_PNGFilter.cc89
1 files changed, 57 insertions, 32 deletions
diff --git a/libqpdf/Pl_PNGFilter.cc b/libqpdf/Pl_PNGFilter.cc
index edcc34cb..5504112e 100644
--- a/libqpdf/Pl_PNGFilter.cc
+++ b/libqpdf/Pl_PNGFilter.cc
@@ -2,32 +2,54 @@
#include <stdexcept>
#include <string.h>
#include <limits.h>
-#include <math.h>
Pl_PNGFilter::Pl_PNGFilter(char const* identifier, Pipeline* next,
action_e action, unsigned int columns,
- unsigned int bytes_per_pixel) :
+ unsigned int samples_per_pixel,
+ unsigned int bits_per_sample) :
Pipeline(identifier, next),
action(action),
- columns(columns),
cur_row(0),
prev_row(0),
buf1(0),
buf2(0),
- bytes_per_pixel(bytes_per_pixel),
pos(0)
{
- if ((columns == 0) || (columns > UINT_MAX - 1))
+ if ((samples_per_pixel < 1) || (samples_per_pixel > 4))
+ {
+ throw std::runtime_error(
+ "PNGFilter created with invalid samples_per_pixel not from 1 to 4");
+ }
+ if (! ((bits_per_sample == 1) ||
+ (bits_per_sample == 2) ||
+ (bits_per_sample == 4) ||
+ (bits_per_sample == 8) ||
+ (bits_per_sample == 16)))
+ {
+ throw std::runtime_error(
+ "PNGFilter created with invalid bits_per_sample not"
+ " 1, 2, 4, 8, or 16");
+ }
+ this->bytes_per_pixel = ((bits_per_sample * samples_per_pixel) + 7) / 8;
+ unsigned long long bpr =
+ ((columns * bits_per_sample * samples_per_pixel) + 7) / 8;
+ if ((bpr == 0) || (bpr > (UINT_MAX - 1)))
{
throw std::runtime_error(
"PNGFilter created with invalid columns value");
}
- this->buf1 = new unsigned char[columns + 1];
- this->buf2 = new unsigned char[columns + 1];
- this->cur_row = buf1;
+ this->bytes_per_row = bpr & UINT_MAX;
+ this->buf1 = new unsigned char[this->bytes_per_row + 1];
+ this->buf2 = new unsigned char[this->bytes_per_row + 1];
+ memset(this->buf1, 0, this->bytes_per_row + 1);
+ memset(this->buf2, 0, this->bytes_per_row + 1);
+ this->cur_row = this->buf1;
+ this->prev_row = this->buf2;
// number of bytes per incoming row
- this->incoming = (action == a_encode ? columns : columns + 1);
+ this->incoming = (action == a_encode ?
+ this->bytes_per_row :
+ this->bytes_per_row + 1);
}
Pl_PNGFilter::~Pl_PNGFilter()
@@ -54,7 +76,7 @@ Pl_PNGFilter::write(unsigned char* data, size_t len)
unsigned char* t = this->prev_row;
this->prev_row = this->cur_row;
this->cur_row = t ? t : this->buf2;
- memset(this->cur_row, 0, this->columns + 1);
+ memset(this->cur_row, 0, this->bytes_per_row + 1);
left = this->incoming;
this->pos = 0;
}
@@ -106,16 +128,16 @@ Pl_PNGFilter::decodeRow()
}
}
- getNext()->write(this->cur_row + 1, this->columns);
+ getNext()->write(this->cur_row + 1, this->bytes_per_row);
}
void
Pl_PNGFilter::decodeSub()
{
unsigned char* buffer = this->cur_row + 1;
- unsigned int bpp = this->bytes_per_pixel != 0 ? this->bytes_per_pixel : 1;
+ unsigned int bpp = this->bytes_per_pixel;
- for (unsigned int i = 0; i < this->columns; ++i)
+ for (unsigned int i = 0; i < this->bytes_per_row; ++i)
{
unsigned char left = 0;
@@ -134,7 +156,7 @@ Pl_PNGFilter::decodeUp()
unsigned char* buffer = this->cur_row + 1;
unsigned char* above_buffer = this->prev_row + 1;
- for (unsigned int i = 0; i < this->columns; ++i)
+ for (unsigned int i = 0; i < this->bytes_per_row; ++i)
{
unsigned char up = above_buffer[i];
buffer[i] += up;
@@ -144,13 +166,14 @@ Pl_PNGFilter::decodeUp()
void
Pl_PNGFilter::decodeAverage()
{
- unsigned char* buffer = this->cur_row+1;
- unsigned char* above_buffer = this->prev_row+1;
- unsigned int bpp = this->bytes_per_pixel != 0 ? this->bytes_per_pixel : 1;
+ unsigned char* buffer = this->cur_row + 1;
+ unsigned char* above_buffer = this->prev_row + 1;
+ unsigned int bpp = this->bytes_per_pixel;
- for (unsigned int i = 0; i < this->columns; ++i)
+ for (unsigned int i = 0; i < this->bytes_per_row; ++i)
{
- int left = 0, up = 0;
+ int left = 0;
+ int up = 0;
if (i >= bpp)
{
@@ -158,22 +181,22 @@ Pl_PNGFilter::decodeAverage()
}
up = above_buffer[i];
- buffer[i] += floor((left+up) / 2);
+ buffer[i] += (left+up) / 2;
}
}
void
Pl_PNGFilter::decodePaeth()
{
- unsigned char* buffer = this->cur_row+1;
- unsigned char* above_buffer = this->prev_row+1;
- unsigned int bpp = this->bytes_per_pixel != 0 ? this->bytes_per_pixel : 1;
+ unsigned char* buffer = this->cur_row + 1;
+ unsigned char* above_buffer = this->prev_row + 1;
+ unsigned int bpp = this->bytes_per_pixel;
- for (unsigned int i = 0; i < this->columns; ++i)
+ for (unsigned int i = 0; i < this->bytes_per_row; ++i)
{
- int left = 0,
- up = above_buffer[i],
- upper_left = 0;
+ int left = 0;
+ int up = above_buffer[i];
+ int upper_left = 0;
if (i >= bpp)
{
@@ -193,10 +216,12 @@ Pl_PNGFilter::PaethPredictor(int a, int b, int c)
int pb = std::abs(p - b);
int pc = std::abs(p - c);
- if (pa <= pb && pa <= pc) {
+ if (pa <= pb && pa <= pc)
+ {
return a;
}
- if (pb <= pc) {
+ if (pb <= pc)
+ {
return b;
}
return c;
@@ -210,7 +235,7 @@ Pl_PNGFilter::encodeRow()
getNext()->write(&ch, 1);
if (this->prev_row)
{
- for (unsigned int i = 0; i < this->columns; ++i)
+ for (unsigned int i = 0; i < this->bytes_per_row; ++i)
{
ch = this->cur_row[i] - this->prev_row[i];
getNext()->write(&ch, 1);
@@ -218,7 +243,7 @@ Pl_PNGFilter::encodeRow()
}
else
{
- getNext()->write(this->cur_row, this->columns);
+ getNext()->write(this->cur_row, this->bytes_per_row);
}
}
@@ -233,7 +258,7 @@ Pl_PNGFilter::finish()
this->prev_row = 0;
this->cur_row = buf1;
this->pos = 0;
- memset(this->cur_row, 0, this->columns + 1);
+ memset(this->cur_row, 0, this->bytes_per_row + 1);
getNext()->finish();
}