[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