Skip to content

Commit 20e1cf8

Browse files
committed
JSON bug fixes
GH pocoproject#241: SF pocoproject#620 Endless loop in JSON parser (added Buffer::setCapacity) GH pocoproject#242: SF pocoproject#619 Syntax error in JSON parser (float/double trim)
1 parent 996ddf1 commit 20e1cf8

8 files changed

Lines changed: 56 additions & 4 deletions

File tree

‎Foundation/include/Poco/Buffer.h‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ class Buffer
142142
{
143143
T* ptr = new T[newCapacity];
144144
if (preserveContent)
145-
std::memcpy(ptr, _ptr, _capacity);
145+
std::memcpy(ptr, _ptr, _used);
146146

147147
delete [] _ptr;
148148
_ptr = ptr;
@@ -151,6 +151,35 @@ class Buffer
151151

152152
_used = newCapacity;
153153
}
154+
155+
void setCapacity(std::size_t newCapacity, bool preserveContent = true)
156+
/// Sets the buffer capacity. If preserveContent is true,
157+
/// the content of the old buffer is copied over to the
158+
/// new buffer. The new capacity can be larger or smaller than
159+
/// the current one; size will be set to the new capacity only if
160+
/// new capacity is smaller than the current size, otherwise it will
161+
/// remain intact.
162+
///
163+
/// Buffers only wrapping externally owned storage can not be
164+
/// resized. If resize is attempted on those, IllegalAccessException
165+
/// is thrown.
166+
{
167+
if (!_ownMem)
168+
throw Poco::InvalidAccessException("Cannot resize buffer which does not own its storage.");
169+
170+
if (newCapacity != _capacity)
171+
{
172+
T* ptr = new T[newCapacity];
173+
if (preserveContent)
174+
std::memcpy(ptr, _ptr, _used < newCapacity ? _used : newCapacity);
175+
176+
delete [] _ptr;
177+
_ptr = ptr;
178+
_capacity = newCapacity;
179+
180+
if (newCapacity < _used) _used = newCapacity;
181+
}
182+
}
154183

155184
void assign(const T* buf, std::size_t sz)
156185
/// Assigns the argument buffer to this buffer.

‎Foundation/src/NumericString.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ bool strToFloat(const std::string& str, float& result, char decSep, char thSep)
233233
using namespace double_conversion;
234234

235235
std::string tmp(str);
236+
trimInPlace(tmp);
236237
removeInPlace(tmp, thSep);
237238
removeInPlace(tmp, 'f');
238239
replaceInPlace(tmp, decSep, '.');
@@ -249,6 +250,7 @@ bool strToDouble(const std::string& str, double& result, char decSep, char thSep
249250
using namespace double_conversion;
250251

251252
std::string tmp(str);
253+
trimInPlace(tmp);
252254
removeInPlace(tmp, thSep);
253255
replaceInPlace(tmp, decSep, '.');
254256
removeInPlace(tmp, 'f');

‎Foundation/testsuite/src/CoreTest.cpp‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,14 @@ void CoreTest::testBuffer()
266266
assert (b.size() == s*2);
267267
assert (b.capacity() == s*2);
268268

269+
b.setCapacity(s * 4);
270+
assert (b.size() == s*2);
271+
assert (b.capacity() == s*4);
272+
273+
b.setCapacity(s);
274+
assert (b.size() == s);
275+
assert (b.capacity() == s);
276+
269277
#if ENABLE_BUGCHECK_TEST
270278
try { int i = b[s]; fail ("must fail"); }
271279
catch (Exception&) { }

‎Foundation/testsuite/src/NumberParserTest.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ void NumberParserTest::testParse()
202202
assertEqualDelta(12.34, NumberParser::parseFloat(format(" 12%c34", dp),dp, ts), 0.01);
203203
assertEqualDelta(12.34, NumberParser::parseFloat(format("12%c34 ", dp), dp, ts), 0.01);
204204
assertEqualDelta(12.34, NumberParser::parseFloat(format(" 12%c34 ", dp), dp, ts), 0.01);
205+
206+
assertEqualDelta(12.34, NumberParser::parseFloat(format("\t\n 12%c34 \v\f\r", dp), dp, ts), 0.01);
205207
}
206208
}
207209
#endif // POCO_NO_FPENVIRONMENT

‎JSON/include/Poco/JSON/Parser.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ inline void Parser::assertNonContainer()
729729

730730
inline void Parser::growBuffer()
731731
{
732-
_parseBuffer.resize(_parseBuffer.size() * 2, true);
732+
_parseBuffer.setCapacity(_parseBuffer.size() * 2, true);
733733
}
734734

735735

‎JSON/src/Parser.cpp‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ Dynamic::Var Parser::parse(const std::string& json)
180180
int c = 0;
181181
while(source.nextChar(c))
182182
{
183-
if (0 == parseChar(c, source)) throw SyntaxException("JSON syntax error");
183+
if (0 == parseChar(c, source))
184+
throw SyntaxException("JSON syntax error");
184185
}
185186

186187
if (!done())
@@ -253,7 +254,7 @@ void Parser::parseBufferPopBackChar()
253254
void Parser::parseBufferPushBackChar(char c)
254255
{
255256
if (_parseBuffer.size() + 1 >= _parseBuffer.capacity())
256-
_parseBuffer.resize(_parseBuffer.capacity() * 2);
257+
_parseBuffer.setCapacity(_parseBuffer.capacity() * 2);
257258

258259
_parseBuffer.append(c);
259260
}

‎JSON/testsuite/src/JSONTest.cpp‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,14 @@ void JSONTest::testUnicode()
16471647
}
16481648

16491649

1650+
void JSONTest::testSmallBuffer()
1651+
{
1652+
Poco::JSON::Parser parser(new Poco::JSON::ParseHandler(), 4);
1653+
std::string jsonStr = "{ \"x\" : \"123456789012345678901234567890123456789012345678901234567890\" }";
1654+
parser.parse(jsonStr);
1655+
}
1656+
1657+
16501658
std::string JSONTest::getTestFilesPath(const std::string& type)
16511659
{
16521660
std::ostringstream ostr;
@@ -1717,6 +1725,7 @@ CppUnit::Test* JSONTest::suite()
17171725
CppUnit_addTest(pSuite, JSONTest, testInvalidUnicodeJanssonFiles);
17181726
CppUnit_addTest(pSuite, JSONTest, testTemplate);
17191727
CppUnit_addTest(pSuite, JSONTest, testUnicode);
1728+
CppUnit_addTest(pSuite, JSONTest, testSmallBuffer);
17201729

17211730
return pSuite;
17221731
}

‎JSON/testsuite/src/JSONTest.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class JSONTest: public CppUnit::TestCase
8686
void testItunes();
8787
void testUnicode();
8888
void testInvalidUnicodeJanssonFiles();
89+
void testSmallBuffer();
8990

9091
void setUp();
9192
void tearDown();

0 commit comments

Comments
 (0)