Commit 2596ca75 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

JSON dec: allowed white spaces for binary strings (bug 509867)



Change-Id: I4a7a4efd408a6045c6c26437d82f9c91ed5addd6
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 3faaf5a9
......@@ -40,6 +40,8 @@ class OCTETSTRING_template;
class CHARSTRING_template;
class UNIVERSAL_CHARSTRING_template;
// Helper functions
extern char hexdigit_to_char(unsigned char hexdigit);
// Additional predefined functions defined in Annex C of ES 101 873-1
......
......@@ -1210,13 +1210,34 @@ int BITSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_
value_len -= 2;
++value;
}
init_struct(value_len);
// White spaces are ignored, so the resulting bitstring might be shorter
// than the extracted JSON string
int bits = value_len;
for (size_t i = 0; i < value_len; ++i) {
if ('0' <= value[i] && '1' >= value[i]) {
set_bit(i, value[i] - '0');
} else {
error = TRUE;
break;
if (value[i] == ' ') {
--bits;
}
else if (value[i] != '0' && value[i] != '1') {
if (value[i] == '\\' && i + 1 < value_len &&
(value[i + 1] == 'n' || value[i + 1] == 'r' || value[i + 1] == 't')) {
// Escaped white space character
++i;
bits -= 2;
}
else {
error = TRUE;
break;
}
}
}
if (!error) {
init_struct(bits);
int bit_index = 0;
for (size_t i = 0; i < value_len; ++i) {
if (value[i] == '0' || value[i] == '1') {
set_bit(bit_index, value[i] - '0');
++bit_index;
}
}
}
} else {
......@@ -1228,9 +1249,6 @@ int BITSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_
if (error) {
JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "bitstring");
if (p_silent) {
clean_up();
}
return JSON_ERROR_FATAL;
}
return (int)dec_len;
......
......@@ -37,6 +37,7 @@
#include "../common/dbgnew.hh"
#include <string.h>
#include <ctype.h>
// hexstring value class
......@@ -1100,14 +1101,36 @@ int HEXSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_
value_len -= 2;
++value;
}
init_struct(value_len);
// White spaces are ignored, so the resulting hexstring might be shorter
// than the extracted JSON string
int nibbles = value_len;
for (size_t i = 0; i < value_len; ++i) {
unsigned char nibble = char_to_hexdigit(value[i]);
if (nibble <= 0x0F) {
set_nibble(i, nibble);
} else {
error = TRUE;
}
if (value[i] == ' ') {
--nibbles;
}
else if (!isxdigit(value[i])) {
if (value[i] == '\\' && i + 1 < value_len &&
(value[i + 1] == 'n' || value[i + 1] == 'r' || value[i + 1] == 't')) {
// Escaped white space character
++i;
nibbles -= 2;
}
else {
error = TRUE;
break;
}
}
}
if (!error) {
init_struct(nibbles);
int nibble_index = 0;
for (size_t i = 0; i < value_len; ++i) {
if (!isxdigit(value[i])) {
continue;
}
set_nibble(nibble_index, char_to_hexdigit(value[i]));
++nibble_index;
}
}
} else {
error = TRUE;
......@@ -1118,9 +1141,6 @@ int HEXSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_
if (error) {
JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "hexstring");
if (p_silent) {
clean_up();
}
return JSON_ERROR_FATAL;
}
return (int)dec_len;
......
......@@ -38,6 +38,7 @@
#include "../common/dbgnew.hh"
#include <string.h>
#include <ctype.h>
// octetstring value class
......@@ -1317,23 +1318,50 @@ int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
return JSON_ERROR_FATAL;
}
else if (JSON_TOKEN_STRING == token || use_default) {
if (0 == value_len % 2 && (use_default ||
(value_len > 2 && value[0] == '\"' && value[value_len - 1] == '\"'))) {
if (use_default || (value_len > 2 && value[0] == '\"' && value[value_len - 1] == '\"')) {
if (!use_default) {
// The default value doesn't have quotes around it
value_len -= 2;
++value;
}
size_t octets = value_len / 2;
init_struct(octets);
for (size_t i = 0; i < octets; ++i) {
unsigned char upper_nibble = char_to_hexdigit(value[2 * i]);
unsigned char lower_nibble = char_to_hexdigit(value[2 * i + 1]);
if (upper_nibble <= 0x0F && lower_nibble <= 0x0F) {
val_ptr->octets_ptr[i] = (upper_nibble << 4) | lower_nibble;
} else {
error = TRUE;
}
// White spaces are ignored, so the resulting octetstring might be shorter
// than the extracted JSON string
int nibbles = value_len;
for (size_t i = 0; i < value_len; ++i) {
if (value[i] == ' ') {
--nibbles;
}
else if (!isxdigit(value[i]) || i + 1 == value_len ||
!isxdigit(value[i + 1])) {
if (value[i] == '\\' && i + 1 < value_len &&
(value[i + 1] == 'n' || value[i + 1] == 'r' || value[i + 1] == 't')) {
// Escaped white space character
++i;
nibbles -= 2;
}
else {
error = TRUE;
break;
}
}
else {
// It's a valid octet (jump through its second nibble)
++i;
}
}
if (!error) {
init_struct(nibbles / 2);
int octet_index = 0;
for (size_t i = 0; i < value_len - 1; ++i) {
if (!isxdigit(value[i]) || !isxdigit(value[i + 1])) {
continue;
}
unsigned char upper_nibble = char_to_hexdigit(value[i]);
unsigned char lower_nibble = char_to_hexdigit(value[i + 1]);
val_ptr->octets_ptr[octet_index] = (upper_nibble << 4) | lower_nibble;
++octet_index;
++i;
}
}
} else {
error = TRUE;
......@@ -1344,9 +1372,6 @@ int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
if (error) {
JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "octetstring");
if (p_silent) {
clean_up();
}
return JSON_ERROR_FATAL;
}
return (int)dec_len;
......
......@@ -555,6 +555,48 @@ testcase tc_asn_optional_null() runs on MTC {
f_bool2verdict(match(f_dec_null(os), c_not_null));
}
// The encodings of binary strings (bitstrings, hexstrings and octetstrings) may contain white spaces.
// White spaces are ignored and the rest of the strings should be decoded correctly.
testcase tc_binary_strings_with_white_spaces() runs on MTC {
var bitstring bs := oct2bit(char2oct("{ \"bit\" : \"10 01\\r00 11\", \"hex\" : \"00 ab c\\t\", \"oct\" : \"ab 12 66\\nc3 d4 f8\" }"));
var BinaryStrings x;
var integer res := decvalue(bs, x);
var BinaryStrings exp := { bit := '10010011'B, hex := '00ABC'H, oct := 'AB1266C3D4F8'O };
if (res != 0) {
setverdict(fail, "Invalid decoding result: ", res, " (expected 0)");
}
else if (x != exp) {
setverdict(fail, "Invalid decoded value. Got: ", x, ", expected: ", exp);
}
else if (bs != ''B) {
setverdict(fail, "Buffer not empty after decoding: ", bs);
}
else {
setverdict(pass);
}
}
// Binary strings (bitstrings, hexstrings and octetstrings) containing invalid characters.
// Decoding should fail with error code 2. The output value should remain unbound and the buffer should remain unchanged after decoding.
testcase tc_binary_strings_with_invalid_chars() runs on MTC {
var bitstring bs := oct2bit(char2oct("{ \"bit\" : \"10,01,00,11\", \"hex\" : \"00 abxc\", \"oct\" : \"ab 12 66\\fc3 d4 f8\" }"));
var bitstring bs_orig := bs;
var BinaryStrings x;
var integer res := decvalue(bs, x);
if (res != 2) {
setverdict(fail, "Invalid decoding result: ", res, " (expected 2)");
}
else if (isbound(x)) {
setverdict(fail, "Value changed during decoding: ", x);
}
else if (bs != bs_orig) {
setverdict(fail, "Buffer changed during decoding: ", bs);
}
else {
setverdict(pass);
}
}
//=========================================================================
// Control
//=========================================================================
......@@ -613,6 +655,9 @@ control {
execute(tc_asn_open_type_and_null());
execute(tc_asn_objid_and_any());
execute(tc_asn_optional_null());
execute(tc_binary_strings_with_white_spaces());
execute(tc_binary_strings_with_invalid_chars());
}
......
......@@ -249,6 +249,12 @@ type record MetainfoOuterRecord {
MetainfoInnerRecord myRec
}
type record BinaryStrings {
bitstring bit,
hexstring hex,
octetstring oct
}
type record of integer MetainfoRecOf
with { variant "JSON: metainfo for unbound"; }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment