Describe the bug
JSON parser used by C# implementation is not enforcing expected value types which can lead to surprising effects.
To Reproduce
Test-invoke this script on preview5 node:
DPJ7Im5hbWUiOnsiYSI6ImIifSwiYWJpIjp7Im1ldGhvZHMiOlt7Im5hbWUiOiJfaW5pdGlhbGl6ZSIsIm9mZnNldCI6MCwicGFyYW1ldGVycyI6W10sInJldHVybnR5cGUiOiJWb2lkIiwic2FmZSI6ZmFsc2V9XSwiZXZlbnRzIjpbXX0sImdyb3VwcyI6W10sInBlcm1pc3Npb25zIjpbeyJjb250cmFjdCI6IioiLCJtZXRob2RzIjoiKiJ9XSwic3VwcG9ydGVkc3RhbmRhcmRzIjpbXSwidHJ1c3RzIjpbXSwiZXh0cmEiOm51bGx9Cg1AAU5FRjNuZW8tZ28tMC45My4wLXByZS0yMTMtZzFiY2EzNmE1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADyVgIMFFx6HTget4LRd8iMo1Q6nW5Dm9f42zBgEGFB6X04oCFhQFcCAnkmNAwsX2RlcGxveSBtZXRob2QgY2FsbGVkIGJlZm9yZSBjb250cmFjdCB1cGRhdGU0ZUVADC5fZGVwbG95IG1ldGhvZCBjYWxsZWQgYmVmb3JlIGNvbnRyYWN0IGNyZWF0aW9uNDFFQFcEAFkAICgGENsgQFhB+CfsjCEmGAwOVmVyaWZpZWQgT3duZXJBz+dHliERQFcDAVkAQCgGENsgQHhBz+dHliERQFcDAVkAQCgGENsgQAwFRXZlbnR4EcBQQZUBb2EhEUB24aSbEsAfDAZkZXBsb3kMFEMOn2+zE6jTordhO2eDCdHX1wGlQWJ9W1I=
It tries to deploy some NEF with this manifest:
{
"name" : {
"a" : "b"
},
"supportedstandards" : [],
"abi" : {
"methods" : [
{
"offset" : 0,
"returntype" : "Void",
"safe" : false,
"name" : "_initialize",
"parameters" : []
}
],
"events" : []
},
"trusts" : [],
"permissions" : [
{
"contract" : "*",
"methods" : "*"
}
],
"extra" : null,
"groups" : []
}
where name field is an object instead of a string.
Expected behavior
neo-go rejects it with
"state": "FAULT",
"gasconsumed": "1001014570",
...
"stack": [],
"exception": "error encountered at instruction 1 (SYSCALL): invalid manifest: json: cannot unmarshal object into Go struct field Manifest.name of type string"
C# node accepts it:
"state": "HALT",
"gasconsumed": "1001014570",
...
"stack": [
{
"type": "Array",
"value": [
{
"type": "Integer",
"value": "8"
},
{
"type": "Integer",
"value": "0"
},
{
"type": "ByteString",
"value": "0AfhcO5IlXn2V6TYAFA/4FBCdAA="
},
{
"type": "ByteString",
"value": "TkVGM25lby1nby0wLjkzLjAtcHJlLTIxMy1nMWJjYTM2YTUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPJWAgwUXHodOB63gtF3yIyjVDqdbkOb1/jbMGAQYUHpfTigIWFAVwICeSY0DCxfZGVwbG95IG1ldGhvZCBjYWxsZWQgYmVmb3JlIGNvbnRyYWN0IHVwZGF0ZTRlRUAMLl9kZXBsb3kgbWV0aG9kIGNhbGxlZCBiZWZvcmUgY29udHJhY3QgY3JlYXRpb240MUVAVwQAWQAgKAYQ2yBAWEH4J+yMISYYDA5WZXJpZmllZCBPd25lckHP50eWIRFAVwMBWQBAKAYQ2yBAeEHP50eWIRFAVwMBWQBAKAYQ2yBADAVFdmVudHgRwFBBlQFvYSERQHbhpJs="
},
{
"type": "Struct",
"value": [
{
"type": "ByteString",
"value": "eyJhIjoiYiJ9"
},
{
"type": "Array",
"value": []
},
{
"type": "Array",
"value": []
},
{
"type": "Struct",
"value": [
{
"type": "Array",
"value": [
{
"type": "Struct",
"value": [
{
"type": "ByteString",
"value": "X2luaXRpYWxpemU="
},
{
"type": "Array",
"value": []
},
{
"type": "Integer",
"value": "255"
},
{
"type": "Integer",
"value": "0"
},
{
"type": "Boolean",
"value": false
}
]
}
]
},
{
"type": "Array",
"value": []
}
]
},
{
"type": "Array",
"value": [
{
"type": "Struct",
"value": [
{
"type": "Any"
},
{
"type": "Any"
}
]
}
]
},
{
"type": "Array",
"value": []
},
{
"type": "ByteString",
"value": "bnVsbA=="
}
]
}
]
}
]
Notice that there is a eyJhIjoiYiJ9 string (which is {"a":"b"}) in the name field of the manifest stack item which is wrong, the original manifest didn't have this string in the name field, it had an object with one field. So this manifest should've been rejected, but it's not.
(Optional) Additional context
I see several potential fixes for this:
- a different parsing strategy
- leaving parsing as is but checking types after parsing (not using overloaded
AsString() basically), though this has to be done everywhere the parser is used
- adding additional schema checking before the parser
Describe the bug
JSON parser used by C# implementation is not enforcing expected value types which can lead to surprising effects.
To Reproduce
Test-invoke this script on preview5 node:
DPJ7Im5hbWUiOnsiYSI6ImIifSwiYWJpIjp7Im1ldGhvZHMiOlt7Im5hbWUiOiJfaW5pdGlhbGl6ZSIsIm9mZnNldCI6MCwicGFyYW1ldGVycyI6W10sInJldHVybnR5cGUiOiJWb2lkIiwic2FmZSI6ZmFsc2V9XSwiZXZlbnRzIjpbXX0sImdyb3VwcyI6W10sInBlcm1pc3Npb25zIjpbeyJjb250cmFjdCI6IioiLCJtZXRob2RzIjoiKiJ9XSwic3VwcG9ydGVkc3RhbmRhcmRzIjpbXSwidHJ1c3RzIjpbXSwiZXh0cmEiOm51bGx9Cg1AAU5FRjNuZW8tZ28tMC45My4wLXByZS0yMTMtZzFiY2EzNmE1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADyVgIMFFx6HTget4LRd8iMo1Q6nW5Dm9f42zBgEGFB6X04oCFhQFcCAnkmNAwsX2RlcGxveSBtZXRob2QgY2FsbGVkIGJlZm9yZSBjb250cmFjdCB1cGRhdGU0ZUVADC5fZGVwbG95IG1ldGhvZCBjYWxsZWQgYmVmb3JlIGNvbnRyYWN0IGNyZWF0aW9uNDFFQFcEAFkAICgGENsgQFhB+CfsjCEmGAwOVmVyaWZpZWQgT3duZXJBz+dHliERQFcDAVkAQCgGENsgQHhBz+dHliERQFcDAVkAQCgGENsgQAwFRXZlbnR4EcBQQZUBb2EhEUB24aSbEsAfDAZkZXBsb3kMFEMOn2+zE6jTordhO2eDCdHX1wGlQWJ9W1I=It tries to deploy some NEF with this manifest:
where
namefield is an object instead of a string.Expected behavior
neo-go rejects it with
C# node accepts it:
Notice that there is a
eyJhIjoiYiJ9string (which is{"a":"b"}) in thenamefield of the manifest stack item which is wrong, the original manifest didn't have this string in thenamefield, it had an object with one field. So this manifest should've been rejected, but it's not.(Optional) Additional context
I see several potential fixes for this:
AsString()basically), though this has to be done everywhere the parser is used