[Pkg-bitcoin-commits] [libunivalue] 67/76: parser: Tighten array, object syntax checks.
Jonas Smedegaard
dr at jones.dk
Mon Apr 4 09:18:33 UTC 2016
This is an automated email from the git hooks/post-receive script.
js pushed a commit to branch master
in repository libunivalue.
commit 3e319f3cf1078fa4b84ede7315bcffb16b77b68a
Author: Jeff Garzik <jeff at bloq.com>
Date: Sat Nov 7 13:00:35 2015 -0500
parser: Tighten array, object syntax checks.
Also, reformat json_isspace() according to style guidelines.
---
include/univalue.h | 43 +++++++++++++++++++++++++----------
lib/univalue_read.cpp | 62 +++++++++++++++++++++++++++++++++++++++------------
test/fail36.json | 1 +
test/unitester.cpp | 1 +
4 files changed, 81 insertions(+), 26 deletions(-)
diff --git a/include/univalue.h b/include/univalue.h
index 13b84fd..932412e 100644
--- a/include/univalue.h
+++ b/include/univalue.h
@@ -243,20 +243,39 @@ extern enum jtokentype getJsonToken(std::string& tokenVal,
unsigned int& consumed, const char *raw);
extern const char *uvTypeName(UniValue::VType t);
+static inline bool jsonTokenIsValue(enum jtokentype jtt)
+{
+ switch (jtt) {
+ case JTOK_OBJ_OPEN:
+ case JTOK_ARR_OPEN:
+ case JTOK_KW_NULL:
+ case JTOK_KW_TRUE:
+ case JTOK_KW_FALSE:
+ case JTOK_NUMBER:
+ case JTOK_STRING:
+ return true;
+
+ default:
+ return false;
+ }
+
+ // not reached
+}
+
static inline bool json_isspace(int ch)
{
- switch (ch) {
- case 0x20:
- case 0x09:
- case 0x0a:
- case 0x0d:
- return true;
-
- default:
- return false;
- }
-
- // not reached
+ switch (ch) {
+ case 0x20:
+ case 0x09:
+ case 0x0a:
+ case 0x0d:
+ return true;
+
+ default:
+ return false;
+ }
+
+ // not reached
}
extern const UniValue NullUniValue;
diff --git a/lib/univalue_read.cpp b/lib/univalue_read.cpp
index 1f0bb95..ab1fba8 100644
--- a/lib/univalue_read.cpp
+++ b/lib/univalue_read.cpp
@@ -242,13 +242,15 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed,
}
enum expect_bits {
- EXP_NAME = (1U << 0),
+ EXP_OBJ_NAME = (1U << 0),
EXP_COLON = (1U << 1),
+ EXP_VALUE = (1U << 3),
+ EXP_ARR_VALUE = (1U << 2),
};
#define expect(bit) (expectMask & (EXP_##bit))
-#define setExpect(bit) { expectMask |= EXP_##bit ; }
-#define clearExpect(bit) { expectMask &= ~EXP_##bit ; }
+#define setExpect(bit) (expectMask |= EXP_##bit)
+#define clearExpect(bit) (expectMask &= ~EXP_##bit)
bool UniValue::read(const char *raw)
{
@@ -269,6 +271,34 @@ bool UniValue::read(const char *raw)
return false;
raw += consumed;
+ bool isValue = jsonTokenIsValue(tok);
+
+ if (expect(VALUE)) {
+ if (!isValue)
+ return false;
+ clearExpect(VALUE);
+
+ } else if (expect(ARR_VALUE)) {
+ bool isArrValue = isValue || (tok == JTOK_ARR_CLOSE);
+ if (!isArrValue)
+ return false;
+
+ clearExpect(ARR_VALUE);
+
+ } else if (expect(OBJ_NAME)) {
+ bool isObjName = (tok == JTOK_OBJ_CLOSE || tok == JTOK_STRING);
+ if (!isObjName)
+ return false;
+
+ } else if (expect(COLON)) {
+ if (tok != JTOK_COLON)
+ return false;
+ clearExpect(COLON);
+
+ } else if (!expect(COLON) && (tok == JTOK_COLON)) {
+ return false;
+ }
+
switch (tok) {
case JTOK_OBJ_OPEN:
@@ -290,13 +320,15 @@ bool UniValue::read(const char *raw)
}
if (utyp == VOBJ)
- setExpect(NAME);
+ setExpect(OBJ_NAME);
+ else
+ setExpect(ARR_VALUE);
break;
}
case JTOK_OBJ_CLOSE:
case JTOK_ARR_CLOSE: {
- if (!stack.size() || expect(COLON) || (last_tok == JTOK_COMMA))
+ if (!stack.size() || (last_tok == JTOK_COMMA))
return false;
VType utyp = (tok == JTOK_OBJ_CLOSE ? VOBJ : VARR);
@@ -305,37 +337,39 @@ bool UniValue::read(const char *raw)
return false;
stack.pop_back();
- clearExpect(NAME);
+ clearExpect(OBJ_NAME);
break;
}
case JTOK_COLON: {
- if (!stack.size() || expect(NAME) || !expect(COLON))
+ if (!stack.size())
return false;
UniValue *top = stack.back();
if (top->getType() != VOBJ)
return false;
- clearExpect(COLON);
+ setExpect(VALUE);
break;
}
case JTOK_COMMA: {
- if (!stack.size() || expect(NAME) || expect(COLON) ||
+ if (!stack.size() ||
(last_tok == JTOK_COMMA) || (last_tok == JTOK_ARR_OPEN))
return false;
UniValue *top = stack.back();
if (top->getType() == VOBJ)
- setExpect(NAME);
+ setExpect(OBJ_NAME);
+ else
+ setExpect(ARR_VALUE);
break;
}
case JTOK_KW_NULL:
case JTOK_KW_TRUE:
case JTOK_KW_FALSE: {
- if (!stack.size() || expect(NAME) || expect(COLON))
+ if (!stack.size())
return false;
UniValue tmpVal;
@@ -359,7 +393,7 @@ bool UniValue::read(const char *raw)
}
case JTOK_NUMBER: {
- if (!stack.size() || expect(NAME) || expect(COLON))
+ if (!stack.size())
return false;
UniValue tmpVal(VNUM, tokenVal);
@@ -375,9 +409,9 @@ bool UniValue::read(const char *raw)
UniValue *top = stack.back();
- if (expect(NAME)) {
+ if (expect(OBJ_NAME)) {
top->keys.push_back(tokenVal);
- clearExpect(NAME);
+ clearExpect(OBJ_NAME);
setExpect(COLON);
} else {
UniValue tmpVal(VSTR, tokenVal);
diff --git a/test/fail36.json b/test/fail36.json
new file mode 100644
index 0000000..f82eb8e
--- /dev/null
+++ b/test/fail36.json
@@ -0,0 +1 @@
+{"a":}
diff --git a/test/unitester.cpp b/test/unitester.cpp
index 73a74d1..5833107 100644
--- a/test/unitester.cpp
+++ b/test/unitester.cpp
@@ -94,6 +94,7 @@ static const char *filenames[] = {
"fail33.json",
"fail34.json",
// "fail35.json", // investigate - issue #15
+ "fail36.json",
"fail3.json",
"fail4.json", // extra comma
"fail5.json",
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-bitcoin/libunivalue.git
More information about the Pkg-bitcoin-commits
mailing list