Skip to content

Json::Exception #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions include/json/assertions.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,30 @@
#include "config.h"
#endif // if !defined(JSON_IS_AMALGAMATION)

/** It should not be possible for a maliciously designed file to
* cause an abort() or seg-fault, so these macros are used only
* for pre-condition violations and internal logic errors.
*/
#if JSON_USE_EXCEPTION
#include <stdexcept>
#define JSON_ASSERT(condition) \
{if (!(condition)) {throw std::logic_error( "assert json failed" );}} // @todo <= add detail about condition in exception
#define JSON_FAIL_MESSAGE(message) \

// @todo <= add detail about condition in exception
# define JSON_ASSERT(condition) \
{if (!(condition)) {Json::throwLogicError( "assert json failed" );}}

# define JSON_FAIL_MESSAGE(message) \
{ \
std::ostringstream oss; oss << message; \
throw std::logic_error(oss.str()); \
Json::throwLogicError(oss.str()); \
abort(); \
}
//#define JSON_FAIL_MESSAGE(message) throw std::logic_error(message)

#else // JSON_USE_EXCEPTION
#define JSON_ASSERT(condition) assert(condition)

# define JSON_ASSERT(condition) assert(condition)

// The call to assert() will show the failure message in debug builds. In
// release bugs we abort, for a core-dump or debugger.
#define JSON_FAIL_MESSAGE(message) \
// release builds we abort, for a core-dump or debugger.
# define JSON_FAIL_MESSAGE(message) \
{ \
std::ostringstream oss; oss << message; \
assert(false && oss.str().c_str()); \
Expand Down
18 changes: 18 additions & 0 deletions include/json/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <string>
#include <vector>
#include <exception>

#ifndef JSON_USE_CPPTL_SMALLMAP
#include <map>
Expand All @@ -32,6 +33,23 @@
*/
namespace Json {

/** Base class for all exceptions we throw.
*/
class JSON_API Exception;
/** Exceptions which the user cannot easily avoid.
*
* E.g. out-of-memory, stack-overflow, malicious input
*/
class JSON_API RuntimeError;
/** Exceptions throw by JSON_ASSERT/JSON_FAIL macros.
*
* These are precondition-violations (user bugs) and internal errors (our bugs).
*/
class JSON_API LogicError;

JSON_API void throwRuntimeError(std::string const& msg);
JSON_API void throwLogicError(std::string const& msg);

/** \brief Type of the value held by a Value object.
*/
enum ValueType {
Expand Down
2 changes: 1 addition & 1 deletion include/json/writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class JSON_API StreamWriter {
/** Write Value into document as configured in sub-class.
Do not take ownership of sout, but maintain a reference during function.
\pre sout != NULL
\return zero on success
\return zero on success (For now, we always return zero, so check the stream instead.)
\throw std::exception possibly, depending on configuration
*/
virtual int write(Value const& root, std::ostream* sout) = 0;
Expand Down
9 changes: 4 additions & 5 deletions src/lib_json/json_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <sstream>
#include <memory>
#include <set>
#include <stdexcept>

#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
#define snprintf _snprintf
Expand Down Expand Up @@ -148,7 +147,7 @@ bool Reader::readValue() {
// But this deprecated class has a security problem: Bad input can
// cause a seg-fault. This seems like a fair, binary-compatible way
// to prevent the problem.
if (stackDepth_g >= stackLimit_g) throw std::runtime_error("Exceeded stackLimit in readValue().");
if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
++stackDepth_g;

Token token;
Expand Down Expand Up @@ -1107,7 +1106,7 @@ bool OurReader::parse(const char* beginDoc,
}

bool OurReader::readValue() {
if (stackDepth_ >= features_.stackLimit_) throw std::runtime_error("Exceeded stackLimit in readValue().");
if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
++stackDepth_;
Token token;
skipCommentTokens(token);
Expand Down Expand Up @@ -1431,7 +1430,7 @@ bool OurReader::readObject(Token& tokenStart) {
return addErrorAndRecover(
"Missing ':' after object member name", colon, tokenObjectEnd);
}
if (name.length() >= (1U<<30)) throw std::runtime_error("keylength >= 2^30");
if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
std::string msg = "Duplicate key: '" + name + "'";
return addErrorAndRecover(
Expand Down Expand Up @@ -1994,7 +1993,7 @@ std::istream& operator>>(std::istream& sin, Value& root) {
"Error from reader: %s",
errs.c_str());

JSON_FAIL_MESSAGE("reader error");
throwRuntimeError("reader error");
}
return sin;
}
Expand Down
57 changes: 51 additions & 6 deletions src/lib_json/json_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ static inline char* duplicateStringValue(const char* value,
length = Value::maxInt - 1;

char* newString = static_cast<char*>(malloc(length + 1));
JSON_ASSERT_MESSAGE(newString != 0,
"in Json::Value::duplicateStringValue(): "
"Failed to allocate string value buffer");
if (newString == NULL) {
throwRuntimeError(
"in Json::Value::duplicateStringValue(): "
"Failed to allocate string value buffer");
}
memcpy(newString, value, length);
newString[length] = 0;
return newString;
Expand All @@ -108,9 +110,11 @@ static inline char* duplicateAndPrefixStringValue(
"length too big for prefixing");
unsigned actualLength = length + sizeof(unsigned) + 1U;
char* newString = static_cast<char*>(malloc(actualLength));
JSON_ASSERT_MESSAGE(newString != 0,
"in Json::Value::duplicateAndPrefixStringValue(): "
"Failed to allocate string value buffer");
if (newString == 0) {
throwRuntimeError(
"in Json::Value::duplicateAndPrefixStringValue(): "
"Failed to allocate string value buffer");
}
*reinterpret_cast<unsigned*>(newString) = length;
memcpy(newString + sizeof(unsigned), value, length);
newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
Expand Down Expand Up @@ -148,6 +152,47 @@ static inline void releaseStringValue(char* value) { free(value); }

namespace Json {

class JSON_API Exception : public std::exception {
public:
Exception(std::string const& msg);
virtual ~Exception() throw();
virtual char const* what() const throw();
protected:
std::string const& msg_;
};
class JSON_API RuntimeError : public Exception {
public:
RuntimeError(std::string const& msg);
};
class JSON_API LogicError : public Exception {
public:
LogicError(std::string const& msg);
};

Exception::Exception(std::string const& msg)
: msg_(msg)
{}
Exception::~Exception() throw()
{}
char const* Exception::what() const throw()
{
return msg_.c_str();
}
RuntimeError::RuntimeError(std::string const& msg)
: Exception(msg)
{}
LogicError::LogicError(std::string const& msg)
: Exception(msg)
{}
void throwRuntimeError(std::string const& msg)
{
throw RuntimeError(msg);
}
void throwLogicError(std::string const& msg)
{
throw LogicError(msg);
}

// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
Expand Down
3 changes: 1 addition & 2 deletions src/lib_json/json_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <sstream>
#include <utility>
#include <set>
#include <stdexcept>
#include <assert.h>
#include <math.h>
#include <stdio.h>
Expand Down Expand Up @@ -1080,7 +1079,7 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const
} else if (cs_str == "None") {
cs = CommentStyle::None;
} else {
throw std::runtime_error("commentStyle must be 'All' or 'None'");
throwRuntimeError("commentStyle must be 'All' or 'None'");
}
std::string colonSymbol = " : ";
if (eyc) {
Expand Down
1 change: 0 additions & 1 deletion src/test_lib_json/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include "jsontest.h"
#include <json/config.h>
#include <json/json.h>
#include <stdexcept>
#include <cstring>

// Make numeric limits more convenient to talk about.
Expand Down