mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-27 02:53:10 +01:00
fixed #592: Incorrect format string in Poco::Dynamic::Struct
This commit is contained in:
@@ -401,6 +401,8 @@ Var Var::parse(const std::string& val, std::string::size_type& pos)
|
||||
return parseObject(val, pos);
|
||||
case '[':
|
||||
return parseArray(val, pos);
|
||||
case '"':
|
||||
return parseJSONString(val, pos);
|
||||
default:
|
||||
return parseString(val, pos);
|
||||
}
|
||||
@@ -464,41 +466,79 @@ Var Var::parseArray(const std::string& val, std::string::size_type& pos)
|
||||
|
||||
std::string Var::parseString(const std::string& val, std::string::size_type& pos)
|
||||
{
|
||||
static const std::string STR_STOP("\"");
|
||||
static const std::string OTHER_STOP("\n ,]}");
|
||||
|
||||
bool inString = false;
|
||||
//skip optional ' "
|
||||
if (val[pos] == '"')
|
||||
{
|
||||
inString = true;
|
||||
++pos;
|
||||
}
|
||||
|
||||
std::string::size_type stop = std::string::npos;
|
||||
if (inString)
|
||||
{
|
||||
stop = val.find_first_of(STR_STOP, pos);
|
||||
if (stop == std::string::npos)
|
||||
throw DataFormatException("Unterminated string");
|
||||
return parseJSONString(val, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we stop at space, ',', ']' or '}' or end of string
|
||||
stop = val.find_first_of(OTHER_STOP, pos);
|
||||
if (stop == std::string::npos)
|
||||
stop = val.size();
|
||||
|
||||
std::string::size_type safeCheck = val.find_first_of(STR_STOP, pos);
|
||||
if (safeCheck != std::string::npos && safeCheck < stop)
|
||||
throw DataFormatException("Misplaced string termination char found");
|
||||
|
||||
std::string result;
|
||||
while (pos < val.size()
|
||||
&& !Poco::Ascii::isSpace(val[pos])
|
||||
&& val[pos] != ','
|
||||
&& val[pos] != ']'
|
||||
&& val[pos] != '}')
|
||||
{
|
||||
result += val[pos++];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// stop now points to the last char to be not included
|
||||
std::string result = val.substr(pos, stop - pos);
|
||||
++stop; // point past '/"
|
||||
pos = stop;
|
||||
|
||||
std::string Var::parseJSONString(const std::string& val, std::string::size_type& pos)
|
||||
{
|
||||
poco_assert_dbg (val[pos] == '"');
|
||||
++pos;
|
||||
std::string result;
|
||||
bool done = false;
|
||||
while (pos < val.size() && !done)
|
||||
{
|
||||
switch (val[pos])
|
||||
{
|
||||
case '"':
|
||||
done = true;
|
||||
++pos;
|
||||
break;
|
||||
case '\\':
|
||||
if (pos < val.size())
|
||||
{
|
||||
++pos;
|
||||
switch (val[pos])
|
||||
{
|
||||
case 'b':
|
||||
result += '\b';
|
||||
break;
|
||||
case 'f':
|
||||
result += '\f';
|
||||
break;
|
||||
case 'n':
|
||||
result += '\n';
|
||||
break;
|
||||
case 'r':
|
||||
result += '\r';
|
||||
break;
|
||||
case 't':
|
||||
result += '\t';
|
||||
break;
|
||||
default:
|
||||
result += val[pos];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += val[pos];
|
||||
}
|
||||
++pos;
|
||||
break;
|
||||
default:
|
||||
result += val[pos++];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!done) throw Poco::DataFormatException("unterminated JSON string");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,43 @@ VarHolder::~VarHolder()
|
||||
namespace Impl {
|
||||
|
||||
|
||||
void escape(std::string& target, const std::string& source)
|
||||
{
|
||||
std::string::const_iterator it(source.begin());
|
||||
std::string::const_iterator end(source.end());
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
switch (*it)
|
||||
{
|
||||
case '"':
|
||||
target += "\\\"";
|
||||
break;
|
||||
case '\\':
|
||||
target += "\\\\";
|
||||
break;
|
||||
case '\b':
|
||||
target += "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
target += "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
target += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
target += "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
target += "\\t";
|
||||
break;
|
||||
default:
|
||||
target += *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool isJSONString(const Var& any)
|
||||
{
|
||||
return any.type() == typeid(std::string) ||
|
||||
@@ -48,9 +85,9 @@ bool isJSONString(const Var& any)
|
||||
|
||||
void appendJSONString(std::string& val, const Var& any)
|
||||
{
|
||||
val.append(1, '"');
|
||||
val.append(any.convert<std::string>());
|
||||
val.append(1, '"');
|
||||
val += '"';
|
||||
escape(val, any.convert<std::string>());
|
||||
val += '"';
|
||||
}
|
||||
|
||||
|
||||
@@ -62,13 +99,21 @@ void appendJSONKey(std::string& val, const Var& any)
|
||||
|
||||
void appendJSONValue(std::string& val, const Var& any)
|
||||
{
|
||||
if (any.isEmpty()) val.append("null");
|
||||
if (any.isEmpty())
|
||||
{
|
||||
val.append("null");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isStr = isJSONString(any);
|
||||
if (isStr) val.append(1, '"');
|
||||
val.append(any.convert<std::string>());
|
||||
if (isStr) val.append(1, '"');
|
||||
if (isStr)
|
||||
{
|
||||
appendJSONString(val, any.convert<std::string>());
|
||||
}
|
||||
else
|
||||
{
|
||||
val.append(any.convert<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user