From 9539f5fe95589c9fc6c53290b4ed5a1af42e0d8c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 20 Feb 2017 19:17:25 +0200 Subject: Allow empty base64Binary value space per spec --- .../cxx/parser/non-validating/base64-binary.cxx | 97 ++++++++------- .../xsde/cxx/parser/validating/base64-binary.cxx | 135 +++++++++++---------- .../parser/validation/built-in/binary/driver.cxx | 21 ++-- 3 files changed, 130 insertions(+), 123 deletions(-) diff --git a/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx b/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx index ac5de47..be48cb0 100644 --- a/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx +++ b/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx @@ -180,10 +180,10 @@ namespace xsde str_.truncate (size); } - // Our length should be a multiple of four. + // Our length should be a multiple of four but it can also be 0. // size_type quad_count = size / 4; - size_type capacity = quad_count * 3 + 1; + size_type capacity = quad_count != 0 ? quad_count * 3 + 1 : 0; #ifdef XSDE_EXCEPTIONS buf_->size (capacity); @@ -194,71 +194,74 @@ namespace xsde return 0; } #endif - char* dst = buf_->data (); + if (quad_count != 0) + { + char* dst = buf_->data (); - // Source and destination indexes. - // - size_type si = 0; - size_type di = 0; + // Source and destination indexes. + // + size_type si = 0; + size_type di = 0; - // Process all quads except the last one. - // - unsigned char b1, b2, b3, b4; + // Process all quads except the last one. + // + unsigned char b1, b2, b3, b4; - for (size_type q = 0; q < quad_count - 1; ++q) - { - b1 = base64_decode (src[si++]); - b2 = base64_decode (src[si++]); - b3 = base64_decode (src[si++]); - b4 = base64_decode (src[si++]); + for (size_type q = 0; q < quad_count - 1; ++q) + { + b1 = base64_decode (src[si++]); + b2 = base64_decode (src[si++]); + b3 = base64_decode (src[si++]); + b4 = base64_decode (src[si++]); - dst[di++] = (b1 << 2) | (b2 >> 4); - dst[di++] = (b2 << 4) | (b3 >> 2); - dst[di++] = (b3 << 6) | b4; - } + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + dst[di++] = (b3 << 6) | b4; + } - // Process the last quad. The first two octets are always there. - // - b1 = base64_decode (src[si++]); - b2 = base64_decode (src[si++]); + // Process the last quad. The first two octets are always there. + // + b1 = base64_decode (src[si++]); + b2 = base64_decode (src[si++]); - char e3 = src[si++]; - char e4 = src[si++]; + char e3 = src[si++]; + char e4 = src[si++]; - if (e4 == '=') - { - if (e3 == '=') + if (e4 == '=') { - // Two pads. Last 4 bits in b2 should be zero. - // - dst[di++] = (b1 << 2) | (b2 >> 4); + if (e3 == '=') + { + // Two pads. Last 4 bits in b2 should be zero. + // + dst[di++] = (b1 << 2) | (b2 >> 4); + } + else + { + // One pad. Last 2 bits in b3 should be zero. + // + b3 = base64_decode (e3); + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + } } else { - // One pad. Last 2 bits in b3 should be zero. + // No pads. // b3 = base64_decode (e3); + b4 = base64_decode (e4); dst[di++] = (b1 << 2) | (b2 >> 4); dst[di++] = (b2 << 4) | (b3 >> 2); + dst[di++] = (b3 << 6) | b4; } - } - else - { - // No pads. - // - b3 = base64_decode (e3); - b4 = base64_decode (e4); - dst[di++] = (b1 << 2) | (b2 >> 4); - dst[di++] = (b2 << 4) | (b3 >> 2); - dst[di++] = (b3 << 6) | b4; + // Set the real size. + // + buf_->size (di); } - // Set the real size. - // - buf_->size (di); - buffer* r = buf_; buf_ = 0; return r; diff --git a/libxsde/xsde/cxx/parser/validating/base64-binary.cxx b/libxsde/xsde/cxx/parser/validating/base64-binary.cxx index 5852da4..e1f35e7 100644 --- a/libxsde/xsde/cxx/parser/validating/base64-binary.cxx +++ b/libxsde/xsde/cxx/parser/validating/base64-binary.cxx @@ -180,16 +180,16 @@ namespace xsde str_.truncate (size); } - // Our length should be a multiple of four. + // Our length should be a multiple of four but if can also be 0. // - if (size == 0 || size % 4 != 0) + if (size % 4 != 0) { _schema_error (schema_error::invalid_base64_binary_value); return; } size_type quad_count = size / 4; - size_type capacity = quad_count * 3 + 1; + size_type capacity = quad_count != 0 ? quad_count * 3 + 1 : 0; #ifdef XSDE_EXCEPTIONS buf_->size (capacity); @@ -200,70 +200,89 @@ namespace xsde return; } #endif - char* dst = buf_->data (); + if (quad_count != 0) + { + char* dst = buf_->data (); - // Source and destination indexes. - // - size_type si = 0; - size_type di = 0; + // Source and destination indexes. + // + size_type si = 0; + size_type di = 0; - // Process all quads except the last one. - // - unsigned char b1, b2, b3, b4; + // Process all quads except the last one. + // + unsigned char b1, b2, b3, b4; - for (size_type q = 0; q < quad_count - 1; ++q) - { + for (size_type q = 0; q < quad_count - 1; ++q) + { + b1 = base64_decode (src[si++]); + b2 = base64_decode (src[si++]); + b3 = base64_decode (src[si++]); + b4 = base64_decode (src[si++]); + + if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF || b4 == 0xFF) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + dst[di++] = (b3 << 6) | b4; + } + + // Process the last quad. The first two octets are always there. + // b1 = base64_decode (src[si++]); b2 = base64_decode (src[si++]); - b3 = base64_decode (src[si++]); - b4 = base64_decode (src[si++]); - if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF || b4 == 0xFF) + if (b1 == 0xFF || b2 == 0xFF) { _schema_error (schema_error::invalid_base64_binary_value); return; } - dst[di++] = (b1 << 2) | (b2 >> 4); - dst[di++] = (b2 << 4) | (b3 >> 2); - dst[di++] = (b3 << 6) | b4; - } - - // Process the last quad. The first two octets are always there. - // - b1 = base64_decode (src[si++]); - b2 = base64_decode (src[si++]); - - if (b1 == 0xFF || b2 == 0xFF) - { - _schema_error (schema_error::invalid_base64_binary_value); - return; - } - - char e3 = src[si++]; - char e4 = src[si++]; + char e3 = src[si++]; + char e4 = src[si++]; - if (e4 == '=') - { - if (e3 == '=') + if (e4 == '=') { - // Two pads. Last 4 bits in b2 should be zero. - // - if ((b2 & 0x0F) != 0) + if (e3 == '=') { - _schema_error (schema_error::invalid_base64_binary_value); - return; + // Two pads. Last 4 bits in b2 should be zero. + // + if ((b2 & 0x0F) != 0) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + dst[di++] = (b1 << 2) | (b2 >> 4); + } + else + { + // One pad. Last 2 bits in b3 should be zero. + // + b3 = base64_decode (e3); + + if (b3 == 0xFF || (b3 & 0x03) != 0) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); } - - dst[di++] = (b1 << 2) | (b2 >> 4); } else { - // One pad. Last 2 bits in b3 should be zero. + // No pads. // b3 = base64_decode (e3); + b4 = base64_decode (e4); - if (b3 == 0xFF || (b3 & 0x03) != 0) + if (b3 == 0xFF || b4 == 0xFF) { _schema_error (schema_error::invalid_base64_binary_value); return; @@ -271,29 +290,13 @@ namespace xsde dst[di++] = (b1 << 2) | (b2 >> 4); dst[di++] = (b2 << 4) | (b3 >> 2); - } - } - else - { - // No pads. - // - b3 = base64_decode (e3); - b4 = base64_decode (e4); - - if (b3 == 0xFF || b4 == 0xFF) - { - _schema_error (schema_error::invalid_base64_binary_value); - return; + dst[di++] = (b3 << 6) | b4; } - dst[di++] = (b1 << 2) | (b2 >> 4); - dst[di++] = (b2 << 4) | (b3 >> 2); - dst[di++] = (b3 << 6) | b4; + // Set the real size. + // + buf_->size (di); } - - // Set the real size. - // - buf_->size (di); } buffer* base64_binary_pimpl:: diff --git a/tests/cxx/parser/validation/built-in/binary/driver.cxx b/tests/cxx/parser/validation/built-in/binary/driver.cxx index 0496f2e..75cfa5d 100644 --- a/tests/cxx/parser/validation/built-in/binary/driver.cxx +++ b/tests/cxx/parser/validation/built-in/binary/driver.cxx @@ -65,6 +65,17 @@ main () base64_binary_pimpl p; p.pre (); p._pre_impl (c); + p._characters (""); + p._post (); + assert (!c.error_type () && + compare (p.post_base64_binary (), "", 0)); + } + + { + context c; + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); p._characters (" \t\n "); p._characters ("MTIzND "); p._characters ("VhYmNqaw = = "); @@ -138,16 +149,6 @@ main () base64_binary_pimpl p; p.pre (); p._pre_impl (c); - // p._characters (""); - p._post (); - assert (c.schema_error () == schema_error::invalid_base64_binary_value); - } - - { - context c; - base64_binary_pimpl p; - p.pre (); - p._pre_impl (c); p._characters ("YQ"); p._post (); assert (c.schema_error () == schema_error::invalid_base64_binary_value); -- cgit v1.1