6 Commits

Author SHA1 Message Date
Michael R Sweet
dc584c0868 PDFio 1.5.4. 2025-08-26 12:33:30 -04:00
Michael R Sweet
4b7e9691b3 PDFio 1.5.4. 2025-08-26 12:32:50 -04:00
Michael R Sweet
795daba88e Fix typos. 2025-08-06 11:26:10 -04:00
Michael R Sweet
ca4f20e84c Clarify token too large errors (Issue #131) 2025-07-28 19:11:17 +01:00
Michael R Sweet
a54e2886a6 Fix copy_jpeg with invalid/corrupt JPEG data (Issue #132) 2025-07-28 19:04:17 +01:00
Michael R Sweet
d3a5fa9e0b Limit generation numbers to 0 to 65535. 2025-07-28 12:51:17 +01:00
10 changed files with 135 additions and 125 deletions

View File

@@ -2,6 +2,15 @@ Changes in PDFio
================ ================
v1.5.4 - 2025-08-26
-------------------
- Updated indirect reference reading code to limit the range of generation
numbers.
- Updated error messages for too large tokens (Issue #131)
- Fixed a JPEG copy bug (Issue #132)
v1.5.3 - 2025-05-03 v1.5.3 - 2025-05-03
------------------- -------------------

24
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for pdfio 1.5.3. # Generated by GNU Autoconf 2.71 for pdfio 1.5.4.
# #
# Report bugs to <https://github.com/michaelrsweet/pdfio/issues>. # Report bugs to <https://github.com/michaelrsweet/pdfio/issues>.
# #
@@ -610,8 +610,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='pdfio' PACKAGE_NAME='pdfio'
PACKAGE_TARNAME='pdfio' PACKAGE_TARNAME='pdfio'
PACKAGE_VERSION='1.5.3' PACKAGE_VERSION='1.5.4'
PACKAGE_STRING='pdfio 1.5.3' PACKAGE_STRING='pdfio 1.5.4'
PACKAGE_BUGREPORT='https://github.com/michaelrsweet/pdfio/issues' PACKAGE_BUGREPORT='https://github.com/michaelrsweet/pdfio/issues'
PACKAGE_URL='https://www.msweet.org/pdfio' PACKAGE_URL='https://www.msweet.org/pdfio'
@@ -1295,7 +1295,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures pdfio 1.5.3 to adapt to many kinds of systems. \`configure' configures pdfio 1.5.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1361,7 +1361,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of pdfio 1.5.3:";; short | recursive ) echo "Configuration of pdfio 1.5.4:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@@ -1460,7 +1460,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
pdfio configure 1.5.3 pdfio configure 1.5.4
generated by GNU Autoconf 2.71 generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc. Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1678,7 +1678,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by pdfio $as_me 1.5.3, which was It was created by pdfio $as_me 1.5.4, which was
generated by GNU Autoconf 2.71. Invocation command line was generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw $ $0$ac_configure_args_raw
@@ -2434,9 +2434,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
PDFIO_VERSION="1.5.3" PDFIO_VERSION="1.5.4"
PDFIO_VERSION_MAJOR="`echo 1.5.3 | awk -F. '{print $1}'`" PDFIO_VERSION_MAJOR="`echo 1.5.4 | awk -F. '{print $1}'`"
PDFIO_VERSION_MINOR="`echo 1.5.3 | awk -F. '{printf("%d\n",$2);}'`" PDFIO_VERSION_MINOR="`echo 1.5.4 | awk -F. '{printf("%d\n",$2);}'`"
@@ -5099,7 +5099,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by pdfio $as_me 1.5.3, which was This file was extended by pdfio $as_me 1.5.4, which was
generated by GNU Autoconf 2.71. Invocation command line was generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -5155,7 +5155,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped' ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\ ac_cs_version="\\
pdfio config.status 1.5.3 pdfio config.status 1.5.4
configured by $0, generated by GNU Autoconf 2.71, configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@@ -21,7 +21,7 @@ AC_PREREQ([2.70])
dnl Package name and version... dnl Package name and version...
AC_INIT([pdfio], [1.5.3], [https://github.com/michaelrsweet/pdfio/issues], [pdfio], [https://www.msweet.org/pdfio]) AC_INIT([pdfio], [1.5.4], [https://github.com/michaelrsweet/pdfio/issues], [pdfio], [https://www.msweet.org/pdfio])
PDFIO_VERSION="AC_PACKAGE_VERSION" PDFIO_VERSION="AC_PACKAGE_VERSION"
PDFIO_VERSION_MAJOR="`echo AC_PACKAGE_VERSION | awk -F. '{print $1}'`" PDFIO_VERSION_MAJOR="`echo AC_PACKAGE_VERSION | awk -F. '{print $1}'`"

View File

@@ -1,7 +1,7 @@
// //
// Simple markdown to PDF converter example for PDFio. // Simple markdown to PDF converter example for PDFio.
// //
// Copyright © 2024 by Michael R Sweet. // Copyright © 2024-2025 by Michael R Sweet.
// //
// Licensed under Apache License v2.0. See the file "LICENSE" for more // Licensed under Apache License v2.0. See the file "LICENSE" for more
// information. // information.
@@ -289,8 +289,8 @@ main(int argc, // I - Number of command-line arguments
// Get the markdown file from the command-line... // Get the markdown file from the command-line...
if (argc < 2 || argc > 3) if (argc < 2 || argc > 3)
{ {
fputs("Usage: md2pdf FILENANE.md [FILENAME.pdf]\n", stderr); fputs("Usage: md2pdf FILENAME.md [FILENAME.pdf]\n", stderr);
fputs(" md2pdf FILENANE.md >FILENAME.pdf\n", stderr); fputs(" md2pdf FILENAME.md >FILENAME.pdf\n", stderr);
return (1); return (1);
} }

View File

@@ -2527,110 +2527,69 @@ copy_jpeg(pdfio_dict_t *dict, // I - Dictionary
bufend += bytes; bufend += bytes;
} }
if (*bufptr == _PDFIO_JPEG_MARKER) if (*bufptr != _PDFIO_JPEG_MARKER)
{ {
// Start of a marker in the file... _pdfioFileError(dict->pdf, "Invalid JPEG data: <%02X>", *bufptr);
bufptr ++; goto finish;
}
marker = *bufptr; // Start of a marker in the file...
length = (size_t)((bufptr[1] << 8) | bufptr[2]); bufptr ++;
bufptr += 3;
if (marker == _PDFIO_JPEG_MARKER) marker = *bufptr;
continue; length = (size_t)((bufptr[1] << 8) | bufptr[2]);
else if (marker == _PDFIO_JPEG_EOI || marker == _PDFIO_JPEG_SOS || length < 2) bufptr += 3;
break;
PDFIO_DEBUG("copy_jpeg: JPEG X'FF%02X' (length %u)\n", marker, (unsigned)length); PDFIO_DEBUG("copy_jpeg: JPEG X'FF%02X' (length %u)\n", marker, (unsigned)length);
length -= 2; if (marker == _PDFIO_JPEG_EOI || marker == _PDFIO_JPEG_SOS || length < 2)
break;
if ((marker >= _PDFIO_JPEG_SOF0 && marker <= _PDFIO_JPEG_SOF3) || (marker >= _PDFIO_JPEG_SOF5 && marker <= _PDFIO_JPEG_SOF7) || (marker >= _PDFIO_JPEG_SOF9 && marker <= _PDFIO_JPEG_SOF11) || (marker >= _PDFIO_JPEG_SOF13 && marker <= _PDFIO_JPEG_SOF15)) length -= 2;
if ((marker >= _PDFIO_JPEG_SOF0 && marker <= _PDFIO_JPEG_SOF3) || (marker >= _PDFIO_JPEG_SOF5 && marker <= _PDFIO_JPEG_SOF7) || (marker >= _PDFIO_JPEG_SOF9 && marker <= _PDFIO_JPEG_SOF11) || (marker >= _PDFIO_JPEG_SOF13 && marker <= _PDFIO_JPEG_SOF15))
{
// SOFn marker, look for dimensions...
//
// Byte(s) Description
// ------- -------------------
// 0 Bits per component
// 1-2 Height
// 3-4 Width
// 5 Number of colors
if (bufptr[0] != 8)
{ {
// SOFn marker, look for dimensions... _pdfioFileError(dict->pdf, "Unable to load %d-bit JPEG image.", bufptr[0]);
// goto finish;
// Byte(s) Description
// ------- -------------------
// 0 Bits per component
// 1-2 Height
// 3-4 Width
// 5 Number of colors
if (bufptr[0] != 8)
{
_pdfioFileError(dict->pdf, "Unable to load %d-bit JPEG image.", bufptr[0]);
goto finish;
}
width = (unsigned)((bufptr[3] << 8) | bufptr[4]);
height = (unsigned)((bufptr[1] << 8) | bufptr[2]);
num_colors = bufptr[5];
}
else if (marker == _PDFIO_JPEG_APP2 && length > 14 && memcmp(bufptr, "ICC_PROFILE", 12))
{
// Portion of ICC profile
int n = bufptr[12], // Chunk number in profile (1-based)
count = bufptr[13]; // Number of chunks
unsigned char *icc_temp; // New ICC buffer
// Discard "ICC_PROFILE\0" and chunk number/count...
bufptr += 14;
length -= 14;
// Expand our ICC buffer...
if ((icc_temp = realloc(icc_data, icc_datalen + length)) == NULL)
return (NULL);
else
icc_data = icc_temp;
// Read the chunk into the ICC buffer...
do
{
if (bufptr >= bufend)
{
// Read more of the marker...
if ((bytes = read(fd, buffer, sizeof(buffer))) <= 0)
{
_pdfioFileError(dict->pdf, "Unable to read JPEG data - %s", strerror(errno));
goto finish;
}
bufptr = buffer;
bufend = buffer + bytes;
}
// Copy from the file buffer to the ICC buffer
if ((bytes = bufend - bufptr) > (ssize_t)length)
bytes = (ssize_t)length;
memcpy(icc_data + icc_datalen, bufptr, bytes);
icc_datalen += (size_t)bytes;
bufptr += bytes;
length -= (size_t)bytes;
}
while (length > 0);
if (n == count && width > 0 && height > 0 && num_colors > 0)
{
// Have everything we need...
break;
}
else
{
// Continue reading...
continue;
}
} }
// Skip past this marker... width = (unsigned)((bufptr[3] << 8) | bufptr[4]);
while (length > 0) height = (unsigned)((bufptr[1] << 8) | bufptr[2]);
num_colors = bufptr[5];
}
else if (marker == _PDFIO_JPEG_APP2 && length > 14 && memcmp(bufptr, "ICC_PROFILE", 12))
{
// Portion of ICC profile
int n = bufptr[12], // Chunk number in profile (1-based)
count = bufptr[13]; // Number of chunks
unsigned char *icc_temp; // New ICC buffer
// Discard "ICC_PROFILE\0" and chunk number/count...
bufptr += 14;
length -= 14;
// Expand our ICC buffer...
if ((icc_temp = realloc(icc_data, icc_datalen + length)) == NULL)
return (NULL);
else
icc_data = icc_temp;
// Read the chunk into the ICC buffer...
do
{ {
bytes = bufend - bufptr; if (bufptr >= bufend)
{
if (length > (size_t)bytes) // Read more of the marker...
{
// Consume everything we have and grab more...
length -= (size_t)bytes;
if ((bytes = read(fd, buffer, sizeof(buffer))) <= 0) if ((bytes = read(fd, buffer, sizeof(buffer))) <= 0)
{ {
_pdfioFileError(dict->pdf, "Unable to read JPEG data - %s", strerror(errno)); _pdfioFileError(dict->pdf, "Unable to read JPEG data - %s", strerror(errno));
@@ -2640,12 +2599,54 @@ copy_jpeg(pdfio_dict_t *dict, // I - Dictionary
bufptr = buffer; bufptr = buffer;
bufend = buffer + bytes; bufend = buffer + bytes;
} }
else
// Copy from the file buffer to the ICC buffer
if ((bytes = bufend - bufptr) > (ssize_t)length)
bytes = (ssize_t)length;
memcpy(icc_data + icc_datalen, bufptr, bytes);
icc_datalen += (size_t)bytes;
bufptr += bytes;
length -= (size_t)bytes;
}
while (length > 0);
if (n == count && width > 0 && height > 0 && num_colors > 0)
{
// Have everything we need...
break;
}
else
{
// Continue reading...
continue;
}
}
// Skip past this marker...
while (length > 0)
{
bytes = bufend - bufptr;
if (length > (size_t)bytes)
{
// Consume everything we have and grab more...
length -= (size_t)bytes;
if ((bytes = read(fd, buffer, sizeof(buffer))) <= 0)
{ {
// Enough at the end of the buffer... _pdfioFileError(dict->pdf, "Unable to read JPEG data - %s", strerror(errno));
bufptr += length; goto finish;
length = 0;
} }
bufptr = buffer;
bufend = buffer + bytes;
}
else
{
// Enough at the end of the buffer...
bufptr += length;
length = 0;
} }
} }
} }

View File

@@ -380,7 +380,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
else else
{ {
// Out of space // Out of space
_pdfioFileError(tb->pdf, "Token too large."); _pdfioFileError(tb->pdf, "String token too large.");
*bufptr = '\0'; *bufptr = '\0';
return (false); return (false);
} }
@@ -408,7 +408,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
if ((2 * (bytes + 1)) > bufsize) if ((2 * (bytes + 1)) > bufsize)
{ {
// Out of space... // Out of space...
_pdfioFileError(tb->pdf, "Token too large."); _pdfioFileError(tb->pdf, "Binary string token too large.");
*bufptr = '\0'; *bufptr = '\0';
return (false); return (false);
} }
@@ -442,7 +442,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
else else
{ {
// Out of space... // Out of space...
_pdfioFileError(tb->pdf, "Token too large."); _pdfioFileError(tb->pdf, "Keyword token too large.");
*bufptr = '\0'; *bufptr = '\0';
return (false); return (false);
} }
@@ -474,7 +474,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
else else
{ {
// Out of space... // Out of space...
_pdfioFileError(tb->pdf, "Token too large."); _pdfioFileError(tb->pdf, "Number token too large.");
*bufptr = '\0'; *bufptr = '\0';
return (false); return (false);
} }
@@ -523,7 +523,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
else else
{ {
// Out of space // Out of space
_pdfioFileError(tb->pdf, "Token too large."); _pdfioFileError(tb->pdf, "Name token too large.");
*bufptr = '\0'; *bufptr = '\0';
return (false); return (false);
} }
@@ -566,7 +566,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
else else
{ {
// Too large // Too large
_pdfioFileError(tb->pdf, "Token too large."); _pdfioFileError(tb->pdf, "Hex string token too large.");
*bufptr = '\0'; *bufptr = '\0';
return (false); return (false);
} }

View File

@@ -515,7 +515,7 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
// Integer... // Integer...
long generation = 0; // Generation number long generation = 0; // Generation number
while (tempptr < tb->bufend && isdigit(*tempptr & 255)) while (tempptr < tb->bufend && generation < 65536 && isdigit(*tempptr & 255))
{ {
generation = generation * 10 + *tempptr - '0'; generation = generation * 10 + *tempptr - '0';
tempptr ++; tempptr ++;

View File

@@ -23,7 +23,7 @@ extern "C" {
// Version numbers... // Version numbers...
// //
# define PDFIO_VERSION "1.5.3" # define PDFIO_VERSION "1.5.4"
# define PDFIO_VERSION_MAJOR 1 # define PDFIO_VERSION_MAJOR 1
# define PDFIO_VERSION_MINOR 5 # define PDFIO_VERSION_MINOR 5

View File

@@ -3,7 +3,7 @@
<metadata> <metadata>
<id>pdfio_native</id> <id>pdfio_native</id>
<title>PDFio Library for VS2019+</title> <title>PDFio Library for VS2019+</title>
<version>1.5.3</version> <version>1.5.4</version>
<authors>Michael R Sweet</authors> <authors>Michael R Sweet</authors>
<owners>michaelrsweet</owners> <owners>michaelrsweet</owners>
<projectUrl>https://github.com/michaelrsweet/pappl</projectUrl> <projectUrl>https://github.com/michaelrsweet/pappl</projectUrl>
@@ -16,7 +16,7 @@
<copyright>Copyright © 2019-2025 by Michael R Sweet</copyright> <copyright>Copyright © 2019-2025 by Michael R Sweet</copyright>
<tags>pdf file native</tags> <tags>pdf file native</tags>
<dependencies> <dependencies>
<dependency id="pdfio_native.redist" version="1.5.3" /> <dependency id="pdfio_native.redist" version="1.5.4" />
<dependency id="libpng_native.redist" version="1.6.30" /> <dependency id="libpng_native.redist" version="1.6.30" />
<dependency id="zlib_native.redist" version="1.2.11" /> <dependency id="zlib_native.redist" version="1.2.11" />
</dependencies> </dependencies>

View File

@@ -3,7 +3,7 @@
<metadata> <metadata>
<id>pdfio_native.redist</id> <id>pdfio_native.redist</id>
<title>PDFio Library for VS2019+</title> <title>PDFio Library for VS2019+</title>
<version>1.5.3</version> <version>1.5.4</version>
<authors>Michael R Sweet</authors> <authors>Michael R Sweet</authors>
<owners>michaelrsweet</owners> <owners>michaelrsweet</owners>
<projectUrl>https://github.com/michaelrsweet/pappl</projectUrl> <projectUrl>https://github.com/michaelrsweet/pappl</projectUrl>