Description
version: latest commit 14bf94c
poc: poc.zip
command: ./jpeg poc /dev/null
The backtrace in gdb:
(gdb) bt
#0 ByteStream::Get (this=0x790ae0) at bytestream.cpp:223
#1 0x000000000042331e in IOStream::PeekWord (this=0x790ae0)
at iostream.cpp:543
#2 0x00000000004c38d5 in Frame::ParseTrailer (this=0x792590, io=0x790ae0)
at frame.cpp:1018
#3 0x000000000043aac9 in JPEG::ReadInternal (this=0x7904c8,
tags=0x7fffffffdd50) at jpeg.cpp:332
#4 0x000000000043988b in JPEG::Read (this=0x7904c8, tags=0x7fffffffdd50)
at jpeg.cpp:210
#5 0x000000000041cabb in Reconstruct (infile=<optimized out>,
outfile=0x7fffffffe70c "/dev/null", colortrafo=1, alpha=0x0, upsample=true)
at reconstruct.cpp:121
#6 0x0000000000408b6a in main (argc=<optimized out>, argv=0x790f29)
at main.cpp:747
Root cause:
There is a loop in frame.cpp:1017-1118.
In line 1018, the program continuously reads marker in the stream by calling IOStream::PeekWord() function.
Line 1018 in 842c7ba
In cases of the default branch, the loop won't exit.
Lines 1088 to 1117 in 842c7ba
The problem is that the IOStream::PeekWord() function might always return a same value.
Specifically, the IOStream::PeekWord() calls ByteStream::Get().
Lines 214 to 224 in 91985dc
IOStream::PeekWord() returns at line 223 with m_pucBufPtr++. However, when using gdb to check the value of m_pucBufPtr, I found that the ByteStream::Get() functions repeatedly read the values from the same address. The 0x790f2a and 0x790f29 correspond to byte1 and byte2 in IOStream::PeekWord() and they never change.
IOStream::PeekWord() then always returns a same value (calculated by byte1 and byte2). Finally, the program never terminates because the return value forces the program to take the default branch.
