summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJelte Jansen <jelte@isc.org>2012-03-29 17:10:45 +0200
committerJelte Jansen <jelte@isc.org>2012-03-29 17:10:45 +0200
commit63e4fc15cc2c66b07168bb15e2e6af464c235a3d (patch)
treeb463f42b901a5e4b52c9e08ff60bd9f24407d74c /src
parent[master] Show testnames when running Python unit tests (diff)
downloadkea-63e4fc15cc2c66b07168bb15e2e6af464c235a3d.tar.xz
kea-63e4fc15cc2c66b07168bb15e2e6af464c235a3d.zip
[1626] escape JSON strings correctly
Diffstat (limited to 'src')
-rw-r--r--src/lib/cc/data.cc28
-rw-r--r--src/lib/cc/tests/data_unittests.cc33
2 files changed, 56 insertions, 5 deletions
diff --git a/src/lib/cc/data.cc b/src/lib/cc/data.cc
index 77f948aea8..8c050fe40d 100644
--- a/src/lib/cc/data.cc
+++ b/src/lib/cc/data.cc
@@ -314,12 +314,21 @@ str_from_stringstream(std::istream &in, const std::string& file, const int line,
} else {
throwJSONError("String expected", file, line, pos);
}
+
while (c != EOF && c != '"') {
- ss << c;
- if (c == '\\' && in.peek() == '"') {
- ss << in.get();
- ++pos;
+ if (c == '\\') {
+ // next char must be either another \ or "
+ // see the spec for allowed escape characters
+ if (strchr("\"\\/\b\f\n\r\t", in.peek()) != NULL) {
+ // drop the escape
+ c = in.get();
+ ++pos;
+ } else {
+ std::cout << "[XX] cur string: " << ss.str() << std::endl;
+ throwJSONError(std::string("Bad escape for: ") + (char)in.peek(), file, line, pos);
+ }
}
+ ss << c;
c = in.get();
++pos;
}
@@ -642,7 +651,16 @@ NullElement::toJSON(std::ostream& ss) const {
void
StringElement::toJSON(std::ostream& ss) const {
ss << "\"";
- ss << stringValue();
+ char c;
+ const std::string& str = stringValue();
+ for (size_t i = 0; i < str.size(); ++i) {
+ c = str[i];
+ // Escape characters as defined in JSON spec
+ if (strchr("\"\\/\b\f\n\r\t", c) != NULL) {
+ ss << '\\';
+ }
+ ss << c;
+ }
ss << "\"";
}
diff --git a/src/lib/cc/tests/data_unittests.cc b/src/lib/cc/tests/data_unittests.cc
index d8624cbaa0..e09b4fee5c 100644
--- a/src/lib/cc/tests/data_unittests.cc
+++ b/src/lib/cc/tests/data_unittests.cc
@@ -20,6 +20,7 @@
using namespace isc::data;
+#include <sstream>
#include <iostream>
using std::oct;
#include <iomanip>
@@ -299,6 +300,38 @@ TEST(Element, create_and_value_throws) {
}
+// Helper for escape check; it puts the given string in a StringElement,
+// then checks for the following conditions:
+// stringValue() must be same as input
+// toJSON() output must be escaped
+// fromJSON() on the previous output must result in original input
+void
+escapeHelper(const std::string& input, const std::string& expected) {
+ StringElement str_element = StringElement(input);
+ EXPECT_EQ(input, str_element.stringValue());
+ std::stringstream os;
+ str_element.toJSON(os);
+ EXPECT_EQ(expected, os.str());
+ ElementPtr str_element2 = Element::fromJSON(os.str());
+ EXPECT_EQ(str_element.stringValue(), str_element2->stringValue());
+}
+
+TEST(Element, escape) {
+ // Test whether quotes are escaped correctly when creating direct
+ // String elements.
+ escapeHelper("foo\"bar", "\"foo\\\"bar\"");
+ escapeHelper("foo\\bar", "\"foo\\\\bar\"");
+ escapeHelper("foo/bar", "\"foo\\/bar\"");
+ escapeHelper("foo\bbar", "\"foo\\\bbar\"");
+ escapeHelper("foo\fbar", "\"foo\\\fbar\"");
+ escapeHelper("foo\nbar", "\"foo\\\nbar\"");
+ escapeHelper("foo\rbar", "\"foo\\\rbar\"");
+ escapeHelper("foo\tbar", "\"foo\\\tbar\"");
+ // Bad escapes
+ EXPECT_THROW(Element::fromJSON("\\a"), JSONError);
+ EXPECT_THROW(Element::fromJSON("\\"), JSONError);
+}
+
TEST(Element, ListElement) {
// this function checks the specific functions for ListElements
ElementPtr el = Element::fromJSON("[ 1, \"bar\", 3 ]");