From 7c04e3aa7be630bb7cef3f992b4f30f8a8d21f79 Mon Sep 17 00:00:00 2001
From: Botond Baranyi <botond.baranyi@ericsson.com>
Date: Tue, 28 Feb 2017 10:35:01 +0100
Subject: [PATCH] Fixed JSON decoding of empty binary strings (bug 512793)

Change-Id: Ic8717cc6f1a5277a1e38050e65ce5786be2f1f59
Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com>
---
 core/Bitstring.cc                   |  2 +-
 core/Hexstring.cc                   |  2 +-
 core/Octetstring.cc                 | 22 ++++++------
 regression_test/json/Testcases.ttcn | 54 +++++++++++++++++++++++++----
 4 files changed, 61 insertions(+), 19 deletions(-)

diff --git a/core/Bitstring.cc b/core/Bitstring.cc
index 953a108d5..af9acb3a9 100644
--- a/core/Bitstring.cc
+++ b/core/Bitstring.cc
@@ -1204,7 +1204,7 @@ int BITSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_
     return JSON_ERROR_FATAL;
   }
   else if (JSON_TOKEN_STRING == token || use_default) {
-    if (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;
diff --git a/core/Hexstring.cc b/core/Hexstring.cc
index f4e520869..390170931 100644
--- a/core/Hexstring.cc
+++ b/core/Hexstring.cc
@@ -1095,7 +1095,7 @@ int HEXSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_
     return JSON_ERROR_FATAL;
   }
   else if (JSON_TOKEN_STRING == token || use_default) {
-    if (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;
diff --git a/core/Octetstring.cc b/core/Octetstring.cc
index 62945fb1c..641747967 100644
--- a/core/Octetstring.cc
+++ b/core/Octetstring.cc
@@ -1318,7 +1318,7 @@ 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 (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;
@@ -1351,16 +1351,18 @@ int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
       }
       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;
+        if (value_len != 0) {
+          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;
           }
-          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 {
diff --git a/regression_test/json/Testcases.ttcn b/regression_test/json/Testcases.ttcn
index 79bf757d3..185ada5ed 100644
--- a/regression_test/json/Testcases.ttcn
+++ b/regression_test/json/Testcases.ttcn
@@ -110,6 +110,13 @@ testcase tc_boolean_false() runs on MTC{
   f_bool2verdict(x==f_dec_bool(os));
 }
 
+testcase tc_charstring_empty() runs on MTC{
+  var charstring cs := ""
+  var octetstring os:= f_enc_cs( cs )
+  f_check_encoding(encoded:= os, expected := char2oct(qm & cs & qm));
+  f_bool2verdict(cs==f_dec_cs(os));
+}
+
 testcase tc_charstring_ascii_basic() runs on MTC{
   var charstring cs := "everything or nothing"
   var octetstring os:= f_enc_cs( cs )
@@ -188,7 +195,12 @@ testcase tc_ucharstring_ascii_extended1_xer() runs on MTC{
 
 
 //========== Universal Charstring =================
-
+testcase tc_ucharstring_empty() runs on MTC{
+  var universal charstring ucs := "";
+  var octetstring os:= f_enc_ucs( ucs )
+  f_check_encoding(encoded:= os, expected := remove_bom(unichar2oct( qm & ucs & qm, "UTF-8")));
+  f_bool2verdict(ucs==f_dec_ucs(os));
+}
 
 
 testcase tc_ucharstring_ascii_basic_long() runs on MTC{
@@ -259,8 +271,15 @@ testcase tc_ucharstring_higherplanes() runs on MTC{
 }
 
 //========= Octetstring ===================
+testcase tc_octetstring_empty() runs on MTC{
+  var octetstring o := ''O;
+  var octetstring os:= f_enc_os( o )
+  f_check_encoding(encoded:= os, expected := '2222'O);
+  f_check_encoding(encoded:= os, expected := qmo & qmo);
+  f_bool2verdict(o == f_dec_os(os));
+}
 
-testcase tc_octetstring() runs on MTC{
+testcase tc_octetstring_nonempty() runs on MTC{
   var octetstring o := '51AD7F32112CC89D'O;
   var octetstring os:= f_enc_os( o )
   f_check_encoding(encoded:= os, expected := '223531414437463332313132434338394422'O);
@@ -270,8 +289,17 @@ testcase tc_octetstring() runs on MTC{
 
 
 //========= Hexstring ===================
+testcase tc_hexstring_empty() runs on MTC{
+  var hexstring h := ''H;
+  log(hex2str(h));
+  var octetstring os:= f_enc_hex( h );
+  
+  f_check_encoding(encoded:= os, expected := '2222'O);
+  f_check_encoding(encoded:= os, expected := qmo & qmo);
+  f_bool2verdict(h == f_dec_hex(os));
+}
 
-testcase tc_hexstring() runs on MTC{
+testcase tc_hexstring_nonempty() runs on MTC{
   var hexstring h := '51AD7F32112CC89D1778DE213A345BA'H;
   log(hex2str(h));
   var octetstring os:= f_enc_hex( h );
@@ -283,7 +311,14 @@ testcase tc_hexstring() runs on MTC{
 
 
 //========= Bitstring ===================
-testcase tc_bitstring() runs on MTC{
+testcase tc_bitstring_empty() runs on MTC{
+  var bitstring bs := ''B;
+  var octetstring os:= f_enc_bit(bs);
+  f_check_encoding(encoded:= os, expected := qmo & char2oct(bit2str(bs)) & qmo);
+  f_bool2verdict(bs == f_dec_bit(os));
+}
+
+testcase tc_bitstring_nonempty() runs on MTC{
   var bitstring bs := '1101001101111011'B;
   var octetstring os:= f_enc_bit(bs);
   f_check_encoding(encoded:= os, expected := qmo & char2oct(bit2str(bs)) & qmo);
@@ -611,6 +646,7 @@ control {
   execute(tc_integer_imported());
   execute(tc_boolean_true());
   execute(tc_boolean_false());
+  execute(tc_charstring_empty());
   execute(tc_charstring_ascii_basic());
   execute(tc_charstring_ascii_basic_long());
   execute(tc_charstring_ascii_basic_long_const());
@@ -619,14 +655,18 @@ control {
   execute(tc_charstring_ascii_extended1());
   execute(tc_charstring_ascii_basic_escapes());
 
+  execute(tc_ucharstring_empty());
   execute(tc_ucharstring_ascii_extended1_xer());
   execute(tc_ucharstring_ascii_extended1());
   execute(tc_ucharstring_ascii_extended2());
   execute(tc_ucharstring_ascii_extended3());
   execute(tc_ucharstring_higherplanes());
-  execute(tc_octetstring());
-  execute(tc_hexstring());
-  execute(tc_bitstring());
+  execute(tc_octetstring_empty());
+  execute(tc_octetstring_nonempty());
+  execute(tc_hexstring_empty());
+  execute(tc_hexstring_nonempty());
+  execute(tc_bitstring_empty());
+  execute(tc_bitstring_nonempty());
   execute(tc_verdicttype());
   execute(tc_float());
   execute(tc_record());
-- 
GitLab