New exception class QPDFSystemError (fixes #221)

This commit is contained in:
Jay Berkenbilt 2018-08-13 19:48:02 -04:00
parent 164cbdde46
commit b4bdc42b4f
7 changed files with 129 additions and 19 deletions

View File

@ -1,3 +1,9 @@
2018-08-13 Jay Berkenbilt <ejb@ql.org>
* Add new class QPDFSystemError, derived from std::runtime_error,
which is now thrown by QUtil::throw_system_error. This enables the
triggering errno value to be retrieved. Fixes #221.
2018-08-12 Jay Berkenbilt <ejb@ql.org>
* qpdf command line: add --no-warn option to suppress issuing

View File

@ -0,0 +1,58 @@
// Copyright (c) 2005-2018 Jay Berkenbilt
//
// This file is part of qpdf.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Versions of qpdf prior to version 7 were released under the terms
// of version 2.0 of the Artistic License. At your option, you may
// continue to consider qpdf to be licensed under those terms. Please
// see the manual for additional information.
#ifndef QPDFSYSTEMERROR_HH
#define QPDFSYSTEMERROR_HH
#include <qpdf/DLL.h>
#include <qpdf/Types.h>
#include <qpdf/Constants.h>
#include <string>
#include <stdexcept>
class QPDFSystemError: public std::runtime_error
{
public:
QPDF_DLL
QPDFSystemError(std::string const& description,
int system_errno);
QPDF_DLL
virtual ~QPDFSystemError() throw ();
// To get a complete error string, call what(), provided by
// std::exception. The accessors below return the original values
// used to create the exception.
QPDF_DLL
std::string const& getDescription() const;
QPDF_DLL
int getErrno() const;
private:
static std::string createWhat(std::string const& description,
int system_errno);
std::string description;
int system_errno;
};
#endif // QPDFSYSTEMERROR_HH

View File

@ -61,9 +61,14 @@ namespace QUtil
QPDF_DLL
unsigned char* unsigned_char_pointer(char const* str);
// Throw std::runtime_error with a string formed by appending to
// Throw QPDFSystemError, which is derived from
// std::runtime_error, with a string formed by appending to
// "description: " the standard string corresponding to the
// current value of errno.
// current value of errno. You can retrieve the value of errno by
// calling getErrno() on the QPDFSystemError. Prior to qpdf 8.2.0,
// this method threw system::runtime_error directly, but since
// QPDFSystemError is derived from system::runtime_error, old code
// that specifically catches std::runtime_error will still work.
QPDF_DLL
void throw_system_error(std::string const& description);

View File

@ -0,0 +1,51 @@
#include <qpdf/QPDFSystemError.hh>
#include <qpdf/QUtil.hh>
#include <string.h>
QPDFSystemError::QPDFSystemError(std::string const& description,
int system_errno) :
std::runtime_error(createWhat(description, system_errno)),
description(description),
system_errno(system_errno)
{
}
QPDFSystemError::~QPDFSystemError() throw ()
{
}
std::string
QPDFSystemError::createWhat(std::string const& description,
int system_errno)
{
std::string message;
#ifdef _MSC_VER
// "94" is mentioned in the MSVC docs, but it's still safe if the
// message is longer. strerror_s is a templated function that
// knows the size of buf and truncates.
char buf[94];
if (strerror_s(buf, errno) != 0)
{
message = description + ": failed with an unknown error";
}
else
{
message = description + ": " + buf;
}
#else
message = description + ": " + strerror(errno);
#endif
return message;
}
std::string const&
QPDFSystemError::getDescription() const
{
return this->description;
}
int
QPDFSystemError::getErrno() const
{
return this->system_errno;
}

View File

@ -7,6 +7,7 @@
# include <qpdf/InsecureRandomDataProvider.hh>
#endif
#include <qpdf/SecureRandomDataProvider.hh>
#include <qpdf/QPDFSystemError.hh>
#include <cmath>
#include <iomanip>
@ -132,22 +133,7 @@ QUtil::unsigned_char_pointer(char const* str)
void
QUtil::throw_system_error(std::string const& description)
{
#ifdef _MSC_VER
// "94" is mentioned in the MSVC docs, but it's still safe if the
// message is longer. strerror_s is a templated function that
// knows the size of buf and truncates.
char buf[94];
if (strerror_s(buf, errno) != 0)
{
throw std::runtime_error(description + ": failed with an unknown error");
}
else
{
throw std::runtime_error(description + ": " + buf);
}
#else
throw std::runtime_error(description + ": " + strerror(errno));
#endif
throw QPDFSystemError(description, errno);
}
int

View File

@ -45,6 +45,7 @@ SRCS_libqpdf = \
libqpdf/QPDFObjectHandle.cc \
libqpdf/QPDFPageDocumentHelper.cc \
libqpdf/QPDFPageObjectHelper.cc \
libqpdf/QPDFSystemError.cc \
libqpdf/QPDFTokenizer.cc \
libqpdf/QPDFWriter.cc \
libqpdf/QPDFXRefEntry.cc \

View File

@ -5,8 +5,10 @@
#include <fcntl.h>
#include <qpdf/QUtil.hh>
#include <qpdf/PointerHolder.hh>
#include <qpdf/QPDFSystemError.hh>
#include <string.h>
#include <limits.h>
#include <assert.h>
#ifdef _WIN32
# include <io.h>
@ -137,9 +139,10 @@ void fopen_wrapper_test()
std::cout << "after fopen" << std::endl;
(void) fclose(f);
}
catch (std::runtime_error& s)
catch (QPDFSystemError& s)
{
std::cout << "exception: " << s.what() << std::endl;
assert(s.getErrno() != 0);
}
}