Skip to content

Commit

Permalink
Revert "Revert "balxml_decoder success on incorrect input {DRQS 17140…
Browse files Browse the repository at this point in the history
…5619} (#4475)" (#4549)" (#4708)

This reverts commit fb97ce4.

  On branch xmlDecoder-171405619
  Changes to be committed:
 	modified:   groups/bal/balxml/balxml.xsd
 	modified:   groups/bal/balxml/balxml_decoder.h
 	modified:   groups/bal/balxml/balxml_decoder.t.cpp
 	modified:   groups/bal/balxml/balxml_decoderoptions.cpp
 	modified:   groups/bal/balxml/balxml_decoderoptions.h
 	modified:   groups/bal/balxml/balxml_encoderoptions.cpp
 	modified:   groups/bal/balxml/balxml_encoderoptions.h
  • Loading branch information
sbreitstein authored and GitHub Enterprise committed May 1, 2024
1 parent f53783e commit dd19020
Show file tree
Hide file tree
Showing 7 changed files with 379 additions and 204 deletions.
11 changes: 11 additions & 0 deletions groups/bal/balxml/balxml.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,17 @@
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name='ValidateRootTag' type='xs:boolean'
minOccurs='0' maxOccurs='1'
default='false'
bdem:allocatesMemory='0'
bdem:allowsDirectManipulation='0'>
<xs:annotation>
<xs:documentation>
Option to validate the root tag when decoding a structure.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>

Expand Down
66 changes: 63 additions & 3 deletions groups/bal/balxml/balxml_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ BSLS_IDENT("$Id: $")
#include <bdlat_nullablevaluefunctions.h>
#include <bdlat_sequencefunctions.h>
#include <bdlat_typecategory.h>
#include <bdlat_typename.h>
#include <bdlat_valuetypefunctions.h>

#include <bdlb_string.h>
Expand All @@ -286,6 +287,7 @@ BSLS_IDENT("$Id: $")
#include <bsl_streambuf.h>
#include <bsl_string.h>
#include <bsl_vector.h>
#include <bsl_cstddef.h> // NULL
#include <bsl_cstring.h>
#include <bsl_cstdlib.h>
#include <bsl_cerrno.h>
Expand Down Expand Up @@ -435,6 +437,12 @@ class Decoder {
int checkForReaderErrors();
int checkForErrors(const ErrorInfo& errInfo);

template <class TYPE>
int validateTopElement(const TYPE *object);
// When decoding a structure, make sure that the root tag of the XML
// matches the structure of the specified 'object' that we are decoding
// into. Return 0 if it does.

void setDecoderError(ErrorInfo::Severity severity, bsl::string_view msg);

int readTopElement();
Expand Down Expand Up @@ -1948,6 +1956,47 @@ int Decoder::warningCount() const
return d_warningCount;
}

template <class TYPE>
inline
int Decoder::validateTopElement(const TYPE *object) {
// If we're decoding a structure (aka 'sequence' or 'choice'), check to
// make sure that the root tag in the XML matches the name of the specified
// 'TYPE' that we are decoding into. If 'TYPE' has not implemented the
// bdlat introspection protocol, then the class name will be NULL, and we
// cannot check it against the tag name.

// has the user asked us to validate the root tag?
if (!d_options->validateRootTag()) {
return 0; // RETURN
}

// Are we decoding a sequence or a choice?
typedef typename bdlat_TypeCategory::Select<TYPE>::Type Category_t;
if (0 == bsl::is_same<bdlat_TypeCategory::Sequence, Category_t>::value &&
0 == bsl::is_same<bdlat_TypeCategory::Choice, Category_t>::value) {
return 0; // RETURN
}

// Do we have introspection on 'TYPE'?
const char *typeName = bdlat_TypeName::className(*object);
if (0 == typeName) { // no introspection support for 'TYPE'
return 0; // RETURN
}

// Does the class name match the root tag?
const char *nodeName = d_reader->nodeName(); // this is the root tag
if (0 == strcmp(nodeName, typeName)) {
return 0; // RETURN
}

BALXML_DECODER_LOG_ERROR(this)
<< "The root object is of type '" << nodeName << "',"
<< " but we're attempting to decode an object of type "
<< "'" << typeName << "'." << BALXML_DECODER_LOG_END;
return -1;
}


inline
int Decoder::open(bsl::istream& stream, const char *uri)
{
Expand Down Expand Up @@ -1986,7 +2035,10 @@ Decoder::decode(bsl::streambuf *buffer, TYPE *object, const char *uri)

}

int ret = this->decode(object);
int ret = validateTopElement(object);
if (0 == ret) {
ret = this->decode(object);
}

switch(errorSeverity()) {
case ErrorInfo::e_NO_ERROR:
Expand Down Expand Up @@ -2018,7 +2070,11 @@ int Decoder::decode(const char *buffer,
return this->errorCount(); // RETURN
}

int ret = this->decode(object);
int ret = validateTopElement(object);
if (0 == ret) {
ret = this->decode(object);
}

this->close();
return ret;
}
Expand All @@ -2031,7 +2087,11 @@ int Decoder::decode(const char *filename, TYPE *object)
return this->errorCount(); // RETURN
}

int ret = this->decode(object);
int ret = validateTopElement(object);
if (0 == ret) {
ret = this->decode(object);
}

this->close();
return ret;
}
Expand Down
94 changes: 92 additions & 2 deletions groups/bal/balxml/balxml_decoder.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
#include <bdlat_typetraits.h>
#include <bdlat_valuetypefunctions.h>

#include <bdlat_typename.h>

#include <bdlb_chartype.h>
#include <bdlb_nullableallocatedvalue.h>
#include <bdlb_nullablevalue.h>
Expand Down Expand Up @@ -190,7 +192,8 @@ namespace Test = s_baltst;
// [ 1] BREATHING TEST
// [16] USAGE EXAMPLES
// [22] REPRODUCE SCENARIO FROM DRQS 169438741
// [23] DECODING CUSTOMIZED HEX AND BASE64 BINARY DATA
// [23] REPRODUCE SCENARIO FROM DRQS 171405619
// [24] DECODING CUSTOMIZED HEX AND BASE64 BINARY DATA
// [-1] TESTING VALID & INVALID UTF-8: e_STRING
// [-1] TESTING VALID & INVALID UTF-8: e_STREAMBUF
// [-1] TESTING VALID & INVALID UTF-8: e_ISTREAM
Expand Down Expand Up @@ -1366,6 +1369,10 @@ const bdlat_SelectionInfo TestChoice2::SELECTION_INFO_ARRAY[] = {
{ 2, "S2", 2, "Selection 2", 0 },
};

const char *bdlat_TypeName_className(const TestChoice2 &) {
return "TestChoice2";
}

// ===============================================
// bdlat_ChoiceFunctions Overrides For TestChoice2
// ===============================================
Expand Down Expand Up @@ -4411,7 +4418,7 @@ int main(int argc, char *argv[])
bsls::ReviewFailureHandlerGuard reviewGuard(&bsls::Review::failByAbort);

switch (test) { case 0: // Zero is always the leading case.
case 23: {
case 24: {
// --------------------------------------------------------------------
// DECODING CUSTOMIZED HEX AND BASE64 BINARY DATA
// This case tests that the decoder can decode elements that are
Expand Down Expand Up @@ -4570,6 +4577,89 @@ int main(int argc, char *argv[])
ASSERTV(LINE, RESULT, RESULT_DATA == data);
}
}
} break;
case 23: {
// --------------------------------------------------------------------
// REPRODUCE SCENARIO FROM DRQS 171405619
//
// Concerns:
//: 1 Decoding a XML input that does not match the type of the class
//: being decoded should cause an error.
//:
//
// Plan:
//: 1 Attempt to decode some XML that contains a structure named
//: 'ErrorEmployee1' into a 'Employee'. Verify that an error is
//: reported. (C-1)
//
// Testing:
// DRQS 171405619
// --------------------------------------------------------------------

if (verbose) cout << "\nREPRODUCE SCENARIO FROM DRQS 171405619"
<< "\n======================================"
<< endl;


balxml::MiniReader reader;
balxml::ErrorInfo errInfo;
balxml::DecoderOptions options;

options.setSkipUnknownElements(false);
options.setValidateRootTag(true);

balxml::Decoder decoder(&options,
&reader,
&errInfo,
&bsl::cerr,
&bsl::cerr);

// Structure - Tag matches
{
bsl::string_view INPUT = "<Employee></Employee>";
bdlsb::FixedMemInStreamBuf isb(INPUT.data(), INPUT.size());
Test::Employee bob;
int rc = decoder.decode(&isb, &bob);
ASSERTV(errInfo.message(), rc, 0 == rc);
}

// Structure - Tag does not match
{
bsl::string_view INPUT
= "<ErrorEmployee1></ErrorEmployee1>";
bdlsb::FixedMemInStreamBuf isb(INPUT.data(), INPUT.size());
Test::Employee bob;
int rc = decoder.decode(&isb, &bob);
ASSERTV(errInfo.message(), rc, 0 != rc);
}

// Choice - Tag matches
{
bsl::string_view INPUT =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
"<TestChoice2 " XSI ">\n"
" <S1>123</S1>\n"
"</TestChoice2>\n";

bdlsb::FixedMemInStreamBuf isb(INPUT.data(), INPUT.size());
TestChoice2 tc;
int rc = decoder.decode(&isb, &tc);
ASSERTV(errInfo.message(), rc, 0 == rc);
}

// Choice - Tag does not match
{
bsl::string_view INPUT =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
"<NotATestChoice2 " XSI ">\n"
" <S1>123</S1>\n"
"</NotATestChoice2>\n";

bdlsb::FixedMemInStreamBuf isb(INPUT.data(), INPUT.size());
TestChoice2 tc;
int rc = decoder.decode(&isb, &tc);
ASSERTV(errInfo.message(), rc, 0 != rc);
}

} break;
case 22: {
Expand Down
Loading

0 comments on commit dd19020

Please sign in to comment.