[Expat-bugs] [ expat-Bugs-3541525 ] Infinite loop in lib/xmlparse.c:XML_GetBuffer

SourceForge.net noreply at sourceforge.net
Thu Jul 26 06:46:57 CEST 2012


Bugs item #3541525, was opened at 2012-07-09 00:12
Message generated for change (Comment added) made by polinenibharat
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=110127&aid=3541525&group_id=10127

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: None
Group: None
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: http://kasten76.myopenid.com/ ()
Assigned to: Nobody/Anonymous (nobody)
Summary: Infinite loop in lib/xmlparse.c:XML_GetBuffer

Initial Comment:
Hi,
first thanks for maintaining expat.

I found this bug in version 2.0.1 but the code is the same in the current developement version.

When XML_GetBuffer is called and bufferSize is 0 it will be initialised to INIT_BUFFER_SIZE (1024). Which is doubled until it is bigger than needeSize (line 1718). For my example neededSize was 
(gdb) p neededSize
$2 = 2128558980

The doubling is optimized to a shift opertaion (gcc 4.7.0). The doubling shifts the true bit in bufferSize out of scope without breaking the loop.

(gdb) p 1024 << 20
$10 = 1073741824
(gdb) p 1024 << 21
$11 = -2147483648
(gdb) p 1024 << 22
$12 = 0

And then goes into an endless loop.

Still searching why the buffer is so huge but i wanted to mention this bug anyway.

Regards.

----------------------------------------------------------------------

Comment By: Bharat (polinenibharat)
Date: 2012-07-25 21:46

Message:
Hi Karl,

There is a small logical overlooking of extreme cases in lines 1718 - 1722,
in lib / xmlparse.c : XML_GetBuffer

******
if (bufferSize == 0)
        bufferSize = INIT_BUFFER_SIZE;
do {
        bufferSize *= 2;
} while (bufferSize < neededSize);

******

Here the do - while is going into an infinite loop because of the Shift
operation << 1
that the compiler is performing at the line 1721 -> bufferSize *= 2;      
Here if bufferSize is 0, this loop is infinite.

Since they are all integers, if the neededSize is anything between [2^30+1,
2^31-1] the bufferSize will eventually shift to become 0 and goes infinite.

To overcome this an easy and simple solution without changing much code
could be to add the line,
bufferSize += 1; ( after line number 1721 ). 

This will ensure that the condition (bufferSize < neededSize) will be
evaluated to false for any value of neededSize, because at some stage
bufferSize will be equal to 2^31-1, the highest possible integer value
before overflow. Since the allotted buffer size can be dynamic based on our
neededSize, it should not change the structure significantly.


final code:
************
if (bufferSize == 0)
        bufferSize = INIT_BUFFER_SIZE;
do {
        bufferSize *= 2;
        bufferSize += 1;
} while (bufferSize < neededSize);

***********
I am new to open source and am sorry I did not know how to submit the patch
at the patch tracker. Hoping it helped. If its ok I'd like to look at as
many open bugs. I really got to liking expat more after looking through the
code :)

----------------------------------------------------------------------

Comment By: Karl Waclawek (kwaclaw)
Date: 2012-07-24 08:59

Message:
We are grateful for patches to Expat bugs. Patches should be submitted to
the Patch tracker. Thank you.

----------------------------------------------------------------------

Comment By: Bharat (polinenibharat)
Date: 2012-07-23 22:59

Message:
Hi this looks great. I started working on it. Please assign it to me.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=110127&aid=3541525&group_id=10127


More information about the Expat-bugs mailing list