Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.

Bug 1151416

Summary: qpid exception text truncated if it would contain \x00 character
Product: Red Hat Enterprise MRG Reporter: Pavel Moravec <pmoravec>
Component: qpid-cppAssignee: Andrew Stitcher <astitcher>
Status: CLOSED WONTFIX QA Contact: Messaging QE <messaging-qe-bugs>
Severity: low Docs Contact:
Priority: medium    
Version: 3.0CC: iboverma, jross, mcressma
Target Milestone: ---Keywords: Reproducer
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-05-22 14:35:13 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Reproducer script none

Description Pavel Moravec 2014-10-10 11:06:11 UTC
Description of problem:
Assume name of some entity (queue, session, XID global ID,..) contains \x00 character and broker wants to raise an exception (and send it over the wire to a client) due to whatever reason.

Broker does so by truncating the exception string at the place of first occurrence of \x00 character, ignoring very informative part of the string (recall an error like "Queue "Wrong": qpid.flow_resume_count=11 must be less than qpid.flow_stop_count=10" being truncated within the queue name).

An exception text needs to contain whole string, ideally with human-unreadable characters replaced by \x values.


Version-Release number of selected component (if applicable):
qpid-cpp 0.22-49


How reproducible:
100%


Steps to Reproduce:
(this is little tricky as I can reproduce it for XID global id at the moment while framing::XID::setGlobalID removes \x00 characters from the provided string; but the reproducer is derived from a real use case)

1. Run broker with trace=yes log-to-file=/tmp/qpidd.log
2. Install Python bitstring library, e.g. from https://pypi.python.org/pypi/bitstring/3.1.3 (download, unpack, and run "python setup.py install" to deploy the lib)
3. Run attached script that just tries to set DTX timeout to 601s on a transaction with \x00 chars inside
4. grep global-id /tmp/qpidd.log


Actual results:
..
2014-10-10 12:56:36 [System] debug Exception constructed: xid {Xid: format=1279348295; global-id=test\x00test\x00test\x00TEST; branch-id=tx-test-1; } has timeout 601 bigger than maximum allowed 600 (/builddir/build/BUILD/qpid-0.22/cpp/src/qpid/broker/SessionAdapter.cpp:663)
2014-10-10 12:56:36 [System] debug Exception constructed: invalid-argument: xid {Xid: format=1279348295; global-id=test
2014-10-10 12:56:36 [Broker] error Execution exception: invalid-argument: xid {Xid: format=1279348295; global-id=test
2014-10-10 12:56:36 [Protocol] trace SENT [qpid.127.0.0.1:5672-127.0.0.1:34457]: Frame[BEbe; channel=1; {ExecutionExceptionBody: error-code=542; command-id=2; class-code=6; command-code=10; field-index=0; description=invalid-argument: xid {Xid: format=1279348295; global-id=test; error-info={}; }]

(see the "Exception constructed" has xid.global-id and compare with xid.global-id in subsequent lines)


Expected results:
"test\x00test\x00test\x00TEST" to be printed everywhere.


Additional info:
One could play with the xid.global-id anyhow (see "global_id = .." in the script), just ensure the hexstream represents 19 bytes (i.e. it is 38 characters from [0-9a-f] )

Comment 1 Pavel Moravec 2014-10-10 11:09:04 UTC
Created attachment 945553 [details]
Reproducer script

Note it requires bitstring python library to work (see bz description for details).

*** IMPORTANT ***
for successfull reproducer, one has to add:

dtx-max-timeout=600

to broker options.

Comment 2 Pavel Moravec 2014-10-14 08:38:05 UTC
For developers:

The key problem is that calling Exception::what() returns const char* that truncates the string at the first occurence of \x00 character.

Possible fix has to rewrite what() function to either return std::string (if possible) or return char* object with \x00 chars replaced by "\x00" string everytime (maybe worth for any human unreadable char).

Some "workaround fix" is to replace e.what() by e.getMessage() like:

Index: src/qpid/amqp_0_10/SessionHandler.cpp
===================================================================
--- src/qpid/amqp_0_10/SessionHandler.cpp	(revision 1628417)
+++ src/qpid/amqp_0_10/SessionHandler.cpp	(working copy)
@@ -94,12 +94,12 @@
         }
     }
     catch(const SessionException& e) {
-        executionException(e.code, e.what());
+        executionException(e.code, /*e.what()*/ e.getMessage());
         framing::AMQP_AllProxy::Execution  execution(channel);
         AMQMethodBody* m = f.getMethod();
         SequenceNumber commandId;
         if (getState()) commandId =  getState()->receiverGetCurrent();
-        execution.exception(e.code, commandId, m ? m->amqpClassId() : 0, m ? m->amqpMethodId() : 0, 0, e.what(), FieldTable());
+        execution.exception(e.code, commandId, m ? m->amqpClassId() : 0, m ? m->amqpMethodId() : 0, 0, /*e.what()*/ e.getMessage(), FieldTable());
         detaching();
         sendDetach();
     }

but this leaves one log instance:

2014-10-14 10:26:51 [Broker] error Execution exception: invalid-argument: xid {Xid: format=1279348295; global-id=test

truncated (as classes derived from Exception like SessionException does not know getMessage mehtod, see cpp/src/qpid/broker/SessionHandler.cpp:46).

Anyway, here at least the client get the whole string from the broker, just one log record is truncated.