Bug Summary

File:programs/Utilities/hddm/hddm-xml.cpp
Location:line 385, column 17
Description:Potential leak of memory pointed to by 'leftovers'

Annotated Source Code

1/*
2 * hddm-xml : tool that reads in a HDDM document (Hall D Data Model)
3 * and translates it into plain-text xml.
4 *
5 * Version 1.3 - Richard Jones, July 2014.
6 * - Added support for input hddm streams with additional features
7 * provided through the c++ API, including on-the-fly compression with
8 * zlib and bzlib2, and per-record crc32 integrity checks.
9 *
10 * Version 1.2 - Richard Jones, December 2005.
11 * - Updated code to use STL strings and vectors instead of old c-style
12 * pre-allocated arrays and strXXX functions.
13 * - Moved functions into classes grouped by function for better clarity.
14 * - Introduced the XStream class library instead of the direct interface
15 * to the rpc/xdr c-library function. This also gives access to a nice
16 * integrated set of compression/decompression streambuf classes.
17 *
18 * Version 1.1 - Richard Jones, September 2003.
19 * - Updated code to work with the new DOM-2 implementation Xerces-c
20 * from apache.org. Significant changes have taken place in the API
21 * since DOM-1.
22 * - Added support for new types "long" (int64), "string" (char arrays of
23 * arbitrary length), and "anyURI" (special case of string).
24 * - Switched from native encoding to the use of the XDR library to make
25 * hddm files machine-independent.
26 *
27 * Original version - Richard Jones, June 4 2001.
28 *
29 *
30 * Programmer's Notes:
31 * -------------------
32 * 1. The output from hddm-xml is a well-formed xml document.
33 *
34 * 2. The hddm stream contains a xml header that functions as a prototype
35 * of the xml output.
36 *
37 * 3. This tool can read any hddm stream. No recompilation is required.
38 *
39 * 4. The code has been tested with the xerces-c DOM implementation from
40 * Apache, and is intended to be used with the xerces-c library.
41 *
42 * 5. Output is sent by default to stdout and can be changed with the
43 * -o option.
44 */
45
46// #define VERBOSE_HDDM_LOGGING 1
47#define BAD_CRC_IS_ONLY_WARNING1 1
48
49#include <xercesc/util/PlatformUtils.hpp>
50#include <xercesc/dom/DOMNamedNodeMap.hpp>
51
52#include "XParsers.hpp"
53#include "XString.hpp"
54
55#include <assert.h>
56#include <stdlib.h>
57#include <stdio.h>
58#include <rpc/rpc.h>
59#include <unistd.h>
60#include <xstream/z.h>
61#include <xstream/bz.h>
62#include <xstream/xdr.h>
63#include <xstream/digest.h>
64
65#include <iostream>
66#include <fstream>
67#include <sstream>
68
69#include "particleType.h"
70
71
72#define X(str)XString(str).unicode_str() XString(str).unicode_str()
73#define S(str)str.c_str() str.c_str()
74
75using namespace xercesc;
76
77int explicit_repeat_count = 1;
78
79class XMLmaker
80{
81 public:
82 std::ofstream xout;
83
84 XMLmaker() {};
85 ~XMLmaker() {};
86
87 void writeXML(const XString& s);
88 void constructXML(xstream::xdr::istream *ifx, DOMElement* el,
89 int size, int depth);
90};
91
92class istreambuffer : public std::streambuf {
93 public:
94 istreambuffer(char* buffer, std::streamsize bufferLength) {
95 setg(buffer, buffer, buffer + bufferLength);
96 }
97
98 std::streampos tellg() {
99 return gptr() - eback();
100 }
101
102 void seekg(std::streampos pos) {
103 reset();
104 gbump(pos);
105 }
106
107 int size() {
108 return egptr() - gptr();
109 }
110
111 void reset() {
112 char *gbegin = eback();
113 char *gend = egptr();
114 setg(gbegin, gbegin, gend);
115 }
116
117 char *getbuf() {
118 return eback();
119 }
120};
121
122class ostreambuffer : public std::streambuf {
123 public:
124 ostreambuffer(char* buffer, std::streamsize bufferLength) {
125 setp(buffer, buffer + bufferLength);
126 }
127
128 std::streampos tellp() {
129 return pptr() - pbase();
130 }
131
132 void seekp(std::streampos pos) {
133 reset();
134 pbump(pos);
135 }
136
137 int size() {
138 return pptr() - pbase();
139 }
140
141 void reset() {
142 char *pbegin = pbase();
143 char *pend = epptr();
144 setp(pbegin, pend);
145 }
146
147 char *getbuf() {
148 return pbase();
149 }
150};
151
152void usage()
153{
154 std::cerr
155 << "\nUsage:\n"
156 << " hddm-xml [-n count] [-o <filename>] [HDDM file]\n\n"
157 << "Options:\n"
158 << " -o <filename> write to <filename>.xml"
159 << std::endl;
160}
161
162
163int main(int argC, char* argV[])
164{
165 XString xFilename;
166
167 try
168 {
169 XMLPlatformUtils::Initialize();
170 }
171 catch (const XMLException* toCatch)
172 {
173 XString msg(toCatch->getMessage());
174 std::cerr
175 << "hddm-xml: Error during initialization! :\n"
176 << S(msg)msg.c_str() << std::endl;
177 return 1;
178 }
179
180 int reqcount=-1;
181 int argInd;
182 for (argInd = 1; argInd < argC; argInd++)
1
Assuming 'argInd' is >= 'argC'
2
Loop condition is false. Execution continues on line 207
183 {
184 if (argV[argInd][0] != '-')
185 {
186 break;
187 }
188 else if (strcmp(argV[argInd],"-o") == 0)
189 {
190 xFilename = argV[++argInd];
191 }
192 else if (strcmp(argV[argInd],"-n") == 0)
193 {
194 if (!sscanf(argV[++argInd],"%d",&reqcount))
195 {
196 usage();
197 return 1;
198 }
199 }
200 else
201 {
202 usage();
203 return 1;
204 }
205 }
206
207 XString hddmFile;
208 std::istream* ifs;
209 if (argInd == argC)
3
Taking true branch
210 {
211 ifs = &std::cin;
212 }
213 else if (argInd == argC - 1)
214 {
215 hddmFile = XString(argV[argInd]);
216 ifs = new std::ifstream(hddmFile.c_str());
217 }
218 else
219 {
220 usage();
221 return 1;
222 }
223 if (!ifs->good())
4
Taking false branch
224 {
225 std::cerr
226 << "hddm-xml: Error opening input stream " << hddmFile << std::endl;
227 exit(1);
228 }
229 std::ostringstream tmpFileStr;
230 tmpFileStr << "tmp" << getpid();
231 std::ofstream ofs(tmpFileStr.str().c_str());
232 if (! ofs.is_open())
5
Taking false branch
233 {
234 std::cerr
235 << "hddm-xml: Error opening temp file " << tmpFileStr.str() << std::endl;
236 exit(2);
237 }
238
239 ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
240 XString xmlHeader;
241 XString line;
242 if (getline(*ifs,line))
6
Taking true branch
243 {
244 if (line.substr(0,5) == "<?xml")
7
Taking false branch
245 {
246 std::cerr
247 << "hddm-xml: Error reading input stream " << hddmFile
248 << std::endl;
249 std::cerr
250 << "Input file appears to be an xml document!" << std::endl;
251 exit(1);
252 }
253 else if (line.substr(0,5) == "<HDDM")
8
Taking true branch
254 {
255 xmlHeader = line + "\n";
256 ofs << line;
257 }
258 else
259 {
260 std::cerr
261 << "hddm-xml: Input stream does not contain valid hddm header"
262 << std::endl;
263 exit(1);
264 }
265 }
266 else
267 {
268 std::cerr
269 << "hddm-xml: Error reading from input stream " << hddmFile
270 << std::endl;
271 exit(1);
272 }
273 while (getline(*ifs,line))
9
Loop condition is true. Entering loop body
11
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
15
Loop condition is true. Entering loop body
274 {
275 ofs << line;
276 if (line == "</HDDM>")
10
Taking false branch
12
Taking false branch
14
Taking false branch
16
Taking true branch
277 {
278 break;
17
Execution continues on line 281
279 }
280 }
281 ofs.close();
282
283#if defined OLD_STYLE_XERCES_PARSER
284 DOMDocument* document = parseInputDocument(tmpFileStr.str().c_str(),false);
285#else
286 DOMDocument* document = buildDOMDocument(tmpFileStr.str().c_str(),false);
287#endif
288 if (document == 0)
18
Assuming 'document' is not equal to null
19
Taking false branch
289 {
290 std::cerr
291 << "hddm-xml : Error parsing HDDM document, "
292 << "cannot continue" << std::endl;
293 return 1;
294 }
295 unlink(tmpFileStr.str().c_str());
296
297 DOMElement* rootEl = document->getDocumentElement();
298 XString rootS(rootEl->getTagName());
299 if (rootS != "HDDM")
20
Taking false branch
300 {
301 std::cerr
302 << "hddm-xml error: root element of input document is "
303 << "\"" << S(rootS)rootS.c_str() << "\", expected \"HDDM\""
304 << std::endl;
305 return 1;
306 }
307
308 XMLmaker builder;
309 if (xFilename.size())
21
Taking false branch
310 {
311 XString fname(xFilename + ".xml");
312 builder.xout.open(fname.c_str());
313 }
314
315 builder.writeXML("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
316 builder.writeXML(xmlHeader);
317
318 int event_buffer_size;
319 char *event_buffer = new char[event_buffer_size = 1000000];
320 istreambuffer *isbuf = new istreambuffer(event_buffer,event_buffer_size);
321 xstream::xdr::istream *ifx = new xstream::xdr::istream(isbuf);
322 int integrity_check_mode = 0;
323 int compression_mode = 0;
324 while (reqcount && ifs->good())
22
Loop condition is true. Entering loop body
32
Loop condition is true. Entering loop body
42
Loop condition is true. Entering loop body
325 {
326 DOMNodeList* contList = rootEl->getChildNodes();
327 int contLength = contList->getLength();
328 int tsize;
329 ifs->read(event_buffer,4);
330 if (ifs->eof()) {
23
Taking false branch
33
Taking false branch
43
Taking false branch
331 break;
332 }
333 isbuf->reset();
334 *ifx >> tsize;
335#ifdef VERBOSE_HDDM_LOGGING
336 XString tnameS(rootEl->getTagName());
337 std::cerr << "hddm-xml : tag " << S(tnameS)tnameS.c_str()
338 << " found with size " << tsize
339 << std::endl;
340#endif
341 if (tsize <= 0)
24
Assuming 'tsize' is > 0
25
Taking false branch
34
Assuming 'tsize' is > 0
35
Taking false branch
44
Assuming 'tsize' is > 0
45
Taking false branch
342 {
343 break;
344 }
345 else if (tsize == 1) {
26
Assuming 'tsize' is not equal to 1
27
Taking false branch
36
Assuming 'tsize' is not equal to 1
37
Taking false branch
46
Assuming 'tsize' is equal to 1
47
Taking true branch
346 int size, format, flags;
347 ifs->read(event_buffer+4,4);
348 *ifx >> size;
349 ifs->read(event_buffer+8,size);
350 *ifx >> format >> flags;
351 int compression_flags = flags & 0xf0;
352 int integrity_flags = flags & 0x0f;
353 std::streambuf *fin_sb = 0;
354 xstream::z::istreambuf *zin_sb = 0;
355 xstream::bz::istreambuf *bzin_sb = 0;
356 int *leftovers = new int[100];
48
Memory is allocated
357 int sizeof_leftovers = sizeof(int[100]);
358 leftovers[0] = 0;
359 if (compression_flags == compression_mode) {
49
Assuming 'compression_flags' is not equal to 'compression_mode'
50
Taking false branch
360 fin_sb = ifs->rdbuf();
361 }
362 else if (size == 8 && format == 0 && compression_flags == 0x10) {
51
Assuming 'size' is not equal to 8
363 if (compression_mode == 0x20) {
364 bzin_sb = (xstream::bz::istreambuf*)ifs->rdbuf();
365 }
366 compression_mode = compression_flags;
367 zin_sb = new xstream::z::istreambuf(ifs->rdbuf(),
368 leftovers, sizeof_leftovers);
369 ifs->rdbuf(zin_sb);
370 if (bzin_sb != 0)
371 delete bzin_sb;
372 }
373 else if (size == 8 && format == 0 && compression_flags == 0x20) {
374 if (compression_mode == 0x10) {
375 zin_sb = (xstream::z::istreambuf*)ifs->rdbuf();
376 }
377 compression_mode = compression_flags;
378 bzin_sb = new xstream::bz::istreambuf(ifs->rdbuf(),
379 leftovers, sizeof_leftovers);
380 ifs->rdbuf(bzin_sb);
381 if (zin_sb != 0)
382 delete zin_sb;
383 }
384 else {
385 if (compression_mode == 0x20) {
52
Potential leak of memory pointed to by 'leftovers'
386 bzin_sb = (xstream::bz::istreambuf*)ifs->rdbuf();
387 fin_sb = bzin_sb->get_streambuf();
388 }
389 else if (compression_mode == 0x10) {
390 zin_sb = (xstream::z::istreambuf*)ifs->rdbuf();
391 fin_sb = zin_sb->get_streambuf();
392 }
393 compression_mode = compression_flags;
394 ifs->rdbuf(fin_sb);
395 if (zin_sb != 0)
396 delete zin_sb;
397 if (bzin_sb != 0)
398 delete bzin_sb;
399 }
400 if (size == 8 && format == 0 && integrity_flags == 0x0) {
401 integrity_check_mode = 0;
402 }
403 else if (size == 8 && format == 0 && integrity_flags == 0x1) {
404 integrity_check_mode = 1;
405 }
406 else {
407 std::cerr << "hddm-xml error: unrecognized stream modifier"
408 " encountered, this stream is no longer readable."
409 << std::endl;
410 break;
411 }
412 continue;
413 }
414 else if (tsize+4 > event_buffer_size) {
28
Taking false branch
38
Taking false branch
415 delete ifx;
416 delete isbuf;
417 char *new_buffer = new char[event_buffer_size = tsize+1000];
418 isbuf = new istreambuffer(new_buffer,event_buffer_size);
419 ifx = new xstream::xdr::istream(isbuf);
420 memcpy(new_buffer,event_buffer,4);
421 *ifx >> tsize;
422 delete[] event_buffer;
423 event_buffer = new_buffer;
424 }
425 ifs->read(event_buffer+4,tsize);
426 --reqcount;
427
428 if (integrity_check_mode == 1) {
29
Taking false branch
39
Taking false branch
429 char crcbuf[10];
430 istreambuffer sbuf(crcbuf,10);
431 xstream::xdr::istream xstr(&sbuf);
432 unsigned int recorded_crc;
433 ifs->read(crcbuf,4);
434 xstr >> recorded_crc;
435 xstream::digest::crc32 crc;
436 std::ostream out(&crc);
437 out.write(event_buffer,tsize+4);
438 out.flush();
439 if (crc.digest() != recorded_crc) {
440#if BAD_CRC_IS_ONLY_WARNING1
441 static int bad_crc_warning_needed = true;
442 char errmsg[] =
443 "WARNING: data integrity crc check failed on input.\n"
444 "This may be the result of a bug in the xstream library\n"
445 "if you are analyzing a data file that was generated by\n"
446 "code prior to svn rev 18530. If this concerns you, \n"
447 "regenerate the file using a newer build of the sim-recon\n"
448 "tools and it should go away.\n";
449 if (bad_crc_warning_needed) {
450 std::cerr << errmsg << std::endl;
451 bad_crc_warning_needed = false;
452 }
453#else
454 std::cerr << "hddm-xml error: crc32 check error on input stream"
455 " encountered, this stream is no longer readable."
456 << std::endl;
457 break;
458#endif
459 }
460 }
461
462 for (int c = 0; c < contLength; c++)
30
Assuming 'c' is >= 'contLength'
31
Loop condition is false. Execution continues on line 324
40
Assuming 'c' is >= 'contLength'
41
Loop condition is false. Execution continues on line 324
463 {
464 DOMNode* cont = contList->item(c);
465 short type = cont->getNodeType();
466 if (type == DOMNode::ELEMENT_NODE)
467 {
468 DOMElement* contEl = (DOMElement*) cont;
469 int size;
470 *ifx >> size;
471#ifdef VERBOSE_HDDM_LOGGING
472 XString cnameS(contEl->getTagName());
473 std::cerr << "hddm-xml : top-level tag " << S(cnameS)cnameS.c_str()
474 << " found with size " << size
475 << std::endl;
476#endif
477 if (size > 0)
478 {
479 builder.constructXML(ifx,contEl,size,1);
480 }
481 else {
482 XString repS(contEl->getAttribute(X("minOccurs")XString("minOccurs").unicode_str()));
483 int rep = (repS == "")? 1 : atoi(S(repS)repS.c_str());
484 if (rep != 0) {
485 XString conameS(contEl->getTagName());
486 std::cerr << "hddm-xml warning: top-level tag " << S(conameS)conameS.c_str()
487 << " found with zero size "
488 << "inside an event with size " << tsize
489 << " continue? [y/n] ";
490 std::string ans;
491 std::cin >> ans;
492 if (ans[0] != 'y' && ans[0] != 'Y') {
493 exit(5);
494 }
495 }
496 }
497 }
498 }
499 }
500
501 builder.writeXML("</HDDM>\n");
502
503 if (ifs != &std::cin)
504 {
505 ((std::ifstream*)ifs)->close();
506 }
507 XMLPlatformUtils::Terminate();
508 return 0;
509}
510
511/* write a string to xml output stream, either stdout or a file */
512
513void XMLmaker::writeXML(const XString& s)
514{
515 if (xout.is_open())
516 {
517 xout << s;
518 }
519 else
520 {
521 std::cout << s;
522 }
523}
524
525/* Generate the output xml document according the DOM;
526 * at entry the buffer pointer bp points the the word after the word count
527 */
528
529void XMLmaker::constructXML(xstream::xdr::istream *ifx,
530 DOMElement* el, int size, int depth)
531{
532 XString tagS(el->getTagName());
533 XString repS(el->getAttribute(X("maxOccurs")XString("maxOccurs").unicode_str()));
534 int rep = (repS == "unbounded")? INT_MAX2147483647 :
535 (repS == "")? 1 :
536 atoi(S(repS)repS.c_str());
537 if (explicit_repeat_count && rep > 1)
538 {
539 *ifx >> rep;
540 size -= 4;
541 }
542
543 int r;
544 for (r = 0; r < rep && size > 0; r++)
545 {
546 for (int d = 0; d < depth; d++)
547 {
548 writeXML(" ");
549 }
550 writeXML("<");
551 writeXML(S(tagS)tagS.c_str());
552 DOMNamedNodeMap* attrList = el->getAttributes();
553 int listLength = attrList->getLength();
554 for (int a = 0; a < listLength; a++)
555 {
556 XString nameS(attrList->item(a)->getNodeName());
557 XString typeS(attrList->item(a)->getNodeValue());
558 std::ostringstream attrStr;
559 if (typeS == "int")
560 {
561 int32_t value;
562 *ifx >> value;
563 size -= 4;
564 attrStr << " " << nameS << "=\"" << value << "\"";
565 }
566 else if (typeS == "long")
567 {
568 int64_t value;
569 *ifx >> value;
570 size -= 8;
571 attrStr << " " << nameS << "=\"" << value << "\"";
572 }
573 else if (typeS == "float")
574 {
575 float value;
576 *ifx >> value;
577 size -= 4;
578 attrStr << " " << nameS << "=\"" << value << "\"";
579 }
580 else if (typeS == "double")
581 {
582 double value;
583 *ifx >> value;
584 size -= 8;
585 attrStr << " " << nameS << "=\"" << value << "\"";
586 }
587 else if (typeS == "boolean")
588 {
589 bool_t value;
590 *ifx >> value;
591 size -= 4;
592 attrStr << " " << nameS << "=\"" << value << "\"";
593 }
594 else if (typeS == "Particle_t")
595 {
596 int32_t value;
597 *ifx >> value;
598 size -= 4;
599 attrStr << " " << nameS << "=\"" << ParticleType((Particle_t)value) << "\"";
600 }
601 else if (typeS == "string" || typeS == "anyURI")
602 {
603 std::string value;
604 *ifx >> value;
605 int strsize = value.size();
606 size -= strsize + 4 + ((strsize % 4)? 4-(strsize % 4) : 0);
607 attrStr << " " << nameS << "=\"" << value << "\"";
608 }
609 else if (nameS == "minOccurs" || nameS == "maxOccurs")
610 {
611 ;
612 }
613 else
614 {
615 attrStr << " " << nameS << "=\"" << typeS << "\"";
616 }
617 writeXML(attrStr.str());
618 }
619
620 DOMNodeList* contList = el->getChildNodes();
621 int contLength = contList->getLength();
622 if (contLength > 1)
623 {
624 writeXML(">\n");
625 }
626 else
627 {
628 writeXML(" />\n");
629 }
630
631 for (int c = 0; c < contLength; c++)
632 {
633 DOMNode* cont = contList->item(c);
634 short type = cont->getNodeType();
635 if (type == DOMNode::ELEMENT_NODE)
636 {
637 DOMElement* contEl = (DOMElement*) cont;
638 int csize;
639 *ifx >> csize;
640 size -= 4;
641#ifdef VERBOSE_HDDM_LOGGING
642 XString cnameS(contEl->getTagName());
643 std::cerr << "hddm-xml : tag " << S(cnameS)cnameS.c_str()
644 << " found with size " << csize
645 << std::endl;
646#endif
647 if (csize > 0) {
648 constructXML(ifx,contEl,csize,depth +1);
649 size -= csize;
650 }
651#ifdef VERBOSE_HDDM_LOGGING
652 else {
653 XString irepS(contEl->getAttribute(X("minOccurs")XString("minOccurs").unicode_str()));
654 int irep = (irepS == "")? 1 : atoi(S(irepS)irepS.c_str());
655 if (irep != 0) {
656 XString conameS(contEl->getTagName());
657 std::cerr << "hddm-xml warning: tag " << S(conameS)conameS.c_str()
658 << " found with zero size, "
659 << "continue? [y/n] ";
660 std::string ans;
661 std::cin >> ans;
662 if (ans[0] != 'y' && ans[0] != 'Y') {
663 exit(5);
664 }
665 }
666 }
667#endif
668 }
669 }
670
671 if (contLength > 1)
672 {
673 for (int d = 0; d < depth; d++)
674 {
675 writeXML(" ");
676 }
677 XString endTag("</"+tagS+">\n");
678 writeXML(endTag);
679 }
680 }
681 if (size != 0) {
682 std::cerr << "hddm-xml : size mismatch in tag " << S(tagS)tagS.c_str()
683 << ", remainder is " << size
684 << ", cannot continue." << std::endl;
685 exit(5);
686 }
687 else if (explicit_repeat_count && r != rep) {
688 std::cerr << "hddm-xml : repeat count mismatch in tag " << S(tagS)tagS.c_str()
689 << ", expected " << rep << " but saw " << r
690 << ", cannot continue." << std::endl;
691 exit(5);
692 }
693}